@automattic/social-previews 3.2.4 → 3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs ADDED
@@ -0,0 +1,2946 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ //#region \0rolldown/runtime.js
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
11
+ key = keys[i];
12
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
13
+ get: ((k) => from[k]).bind(null, key),
14
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
15
+ });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
20
+ value: mod,
21
+ enumerable: true
22
+ }) : target, mod));
23
+ //#endregion
24
+ let _wordpress_element = require("@wordpress/element");
25
+ let _wordpress_i18n = require("@wordpress/i18n");
26
+ let react_jsx_runtime = require("react/jsx-runtime");
27
+ let react = require("react");
28
+ let clsx = require("clsx");
29
+ clsx = __toESM(clsx);
30
+ let _wordpress_components = require("@wordpress/components");
31
+ //#region src/helpers.tsx
32
+ const baseDomain = (url) => {
33
+ const withoutProtocol = url.replace(/^[^/]+:\/\//, "");
34
+ const slashIndex = withoutProtocol.indexOf("/");
35
+ return slashIndex === -1 ? withoutProtocol : withoutProtocol.substring(0, slashIndex);
36
+ };
37
+ /**
38
+ * Counts Unicode codepoints rather than UTF-16 code units, so an emoji like 🚀
39
+ * is one character (matching PHP `mb_strlen`) rather than two. Lets the JS
40
+ * preview's truncation align with the backend's logical-char counting.
41
+ *
42
+ * @param text - The string to measure.
43
+ * @return The codepoint count.
44
+ */
45
+ const codepointLength$1 = (text) => Array.from(text).length;
46
+ /**
47
+ * Slices a string by Unicode codepoints rather than UTF-16 code units, so
48
+ * surrogate pairs (most emoji) are never split mid-character.
49
+ *
50
+ * @param text - The string to slice.
51
+ * @param start - Start index, in codepoints.
52
+ * @param end - End index, in codepoints (exclusive).
53
+ * @return The sliced string.
54
+ */
55
+ const codepointSlice = (text, start, end) => Array.from(text).slice(start, end).join("");
56
+ const shortEnough = (limit) => (title) => codepointLength$1(title) <= limit ? title : false;
57
+ const truncatedAtSpace = (lower, upper) => (fullTitle) => {
58
+ const title = fullTitle.slice(0, upper);
59
+ const lastSpace = title.lastIndexOf(" ");
60
+ return lastSpace > lower && lastSpace < upper ? title.slice(0, lastSpace).concat("…") : false;
61
+ };
62
+ const hardTruncation = (limit) => (title) => codepointSlice(title, 0, limit).concat("…");
63
+ const firstValid = (...predicates) => (a) => predicates.find((p) => false !== p(a))?.(a);
64
+ const stripHtmlTags = (description, allowedTags = []) => {
65
+ const pattern = new RegExp(`(<([^${allowedTags.join("")}>]+)>)`, "gi");
66
+ return description ? description.replace(pattern, "") : "";
67
+ };
68
+ /**
69
+ * For social note posts we use the first 50 characters of the description.
70
+ * @param description - The post description.
71
+ * @return The first 50 characters of the description.
72
+ */
73
+ const getTitleFromDescription = (description) => {
74
+ return stripHtmlTags(description).substring(0, 50);
75
+ };
76
+ const hasTag = (text, tag) => {
77
+ return new RegExp(`<${tag}[^>]*>`, "gi").test(text);
78
+ };
79
+ const formatNextdoorDate = new Intl.DateTimeFormat("en-GB", {
80
+ day: "numeric",
81
+ month: "short"
82
+ }).format;
83
+ const formatThreadsDate = new Intl.DateTimeFormat("en-US", {
84
+ day: "2-digit",
85
+ month: "2-digit",
86
+ year: "numeric"
87
+ }).format;
88
+ const formatTweetDate = new Intl.DateTimeFormat("en-US", {
89
+ month: "short",
90
+ day: "numeric"
91
+ }).format;
92
+ const formatMastodonDate = new Intl.DateTimeFormat("en-US", {
93
+ month: "short",
94
+ day: "numeric",
95
+ year: "numeric"
96
+ }).format;
97
+ const collapseWhitespace = (text) => text.replace(/\s+/g, " ").trim();
98
+ const countOccurrences = (haystack, needle) => {
99
+ let count = 0;
100
+ for (let pos = haystack.indexOf(needle); pos !== -1; pos = haystack.indexOf(needle, pos + 1)) count++;
101
+ return count;
102
+ };
103
+ const nthIndexOf = (haystack, needle, n) => {
104
+ let pos = haystack.indexOf(needle);
105
+ while (pos !== -1 && n > 0) {
106
+ n--;
107
+ pos = haystack.indexOf(needle, pos + 1);
108
+ }
109
+ return pos;
110
+ };
111
+ /**
112
+ * Extracts `(text, href)` pairs from `<a href="…">text</a>` in HTML, skipping
113
+ * autolinks (text already equals the URL) and non-http(s) hrefs. Mirrors the
114
+ * backend `ExtractorUtils::get_anchor_links_from_html` so the preview links the
115
+ * same anchors the published share will.
116
+ *
117
+ * @param html - Raw post content HTML.
118
+ * @return The editor hyperlinks found, in document order.
119
+ */
120
+ function parseHyperlinks(html) {
121
+ if (!html) return [];
122
+ const doc = document.implementation.createHTMLDocument("");
123
+ doc.body.innerHTML = html;
124
+ const links = [];
125
+ for (const anchor of Array.from(doc.body.querySelectorAll("a[href]"))) {
126
+ const href = anchor.getAttribute("href") ?? "";
127
+ const text = collapseWhitespace(anchor.textContent ?? "");
128
+ if (!/^https?:\/\//i.test(href) || "" === text || text === href) continue;
129
+ const range = doc.createRange();
130
+ range.selectNodeContents(doc.body);
131
+ range.setEndBefore(anchor);
132
+ const occurrence = countOccurrences(collapseWhitespace(range.toString()), text);
133
+ links.push({
134
+ text,
135
+ href,
136
+ occurrence
137
+ });
138
+ }
139
+ return links;
140
+ }
141
+ const hashtagUrlMap = {
142
+ twitter: "https://twitter.com/hashtag/%1$s",
143
+ facebook: "https://www.facebook.com/hashtag/%1$s",
144
+ linkedin: "https://www.linkedin.com/feed/hashtag/?keywords=%1$s",
145
+ instagram: "https://www.instagram.com/explore/tags/%1$s",
146
+ mastodon: "https://%2$s/tags/%1$s",
147
+ nextdoor: "https://nextdoor.com/hashtag/%1$s",
148
+ threads: "https://www.threads.net/search?q=%1$s&serp_type=tags",
149
+ tumblr: "https://www.tumblr.com/tagged/%1$s",
150
+ bluesky: "https://bsky.app/hashtag/%1$s"
151
+ };
152
+ /**
153
+ * Prepares the text for the preview.
154
+ * @param {string} text - The text to prepare.
155
+ * @param {PreviewTextOptions} options - The options for preparing the text.
156
+ * @return The prepared text as React nodes.
157
+ */
158
+ function preparePreviewText(text, options) {
159
+ const { platform, maxChars, maxLines, hyperlinkHashtags = true, hyperlinkUrls = "instagram" !== platform, hyperlinks } = options;
160
+ let result = stripHtmlTags(text);
161
+ result = result.replaceAll(/(?:\s*[\n\r]){2,}/g, "\n\n");
162
+ if (maxChars && codepointLength$1(result) > maxChars) result = hardTruncation(maxChars)(result);
163
+ if (maxLines) {
164
+ const lines = result.split("\n");
165
+ if (lines.length > maxLines) result = lines.slice(0, maxLines).join("\n");
166
+ }
167
+ const componentMap = {};
168
+ if (hyperlinkUrls)
169
+ /**
170
+ * BEFORE:
171
+ * result = 'Check out this cool site: https://wordpress.org and this one: https://wordpress.com'
172
+ */
173
+ (result.match(/(https?:\/\/\S+)/g) || []).forEach((url, index) => {
174
+ componentMap[`Link${index}`] = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
175
+ href: url,
176
+ rel: "noopener noreferrer",
177
+ target: "_blank",
178
+ children: url
179
+ });
180
+ result = result.replace(url, `<Link${index} />`);
181
+ });
182
+ if (hyperlinkHashtags && hashtagUrlMap[platform]) {
183
+ /**
184
+ * We need to ensure that only the standalone hashtags are matched.
185
+ * For example, we don't want to match the hash in the URL.
186
+ * Thus we need to match the whitespace character before the hashtag or the beginning of the string.
187
+ */
188
+ const hashtags = result.matchAll(/(^|\s)#(\w+)/g);
189
+ const hashtagUrl = hashtagUrlMap[platform];
190
+ /**
191
+ * BEFORE:
192
+ * result = `#breaking text with a #hashtag on the #web
193
+ * with a url https://github.com/Automattic/wp-calypso#security that has a hash in it`
194
+ */
195
+ [...hashtags].forEach(([fullMatch, whitespace, hashtag], index) => {
196
+ const url = (0, _wordpress_i18n.sprintf)(hashtagUrl, hashtag, options.hashtagDomain);
197
+ componentMap[`Hashtag${index}`] = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
198
+ href: url,
199
+ rel: "noopener noreferrer",
200
+ target: "_blank",
201
+ children: `#${hashtag}`
202
+ });
203
+ result = result.replace(fullMatch, `${whitespace}<Hashtag${index} />`);
204
+ });
205
+ }
206
+ if (hyperlinks?.length) {
207
+ const matches = [];
208
+ hyperlinks.forEach(({ text: anchorText, href, occurrence = 0 }, index) => {
209
+ if (!anchorText) return;
210
+ const pos = nthIndexOf(result, anchorText, occurrence);
211
+ if (pos === -1) return;
212
+ if (!matches.some((match) => pos < match.pos + match.text.length && match.pos < pos + anchorText.length)) matches.push({
213
+ pos,
214
+ text: anchorText,
215
+ href,
216
+ index
217
+ });
218
+ });
219
+ matches.sort((a, b) => b.pos - a.pos);
220
+ for (const { pos, text: anchorText, href, index } of matches) {
221
+ const token = `Hyperlink${index}`;
222
+ componentMap[token] = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
223
+ href,
224
+ rel: "noopener noreferrer",
225
+ target: "_blank"
226
+ });
227
+ const wrapped = `<${token}>${anchorText}</${token}>`;
228
+ result = result.slice(0, pos) + wrapped + result.slice(pos + anchorText.length);
229
+ }
230
+ }
231
+ /**
232
+ * BEFORE:
233
+ * result = 'This is a text\nwith a newline\nin it'
234
+ */
235
+ result = result.replace(/\n/g, "<br />");
236
+ componentMap.br = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("br", {});
237
+ /**
238
+ * AFTER:
239
+ * result = 'This is a text<br />with a newline<br />in it'
240
+ * componentMap = { br: <br /> }
241
+ */
242
+ return (0, _wordpress_element.createInterpolateElement)(result, componentMap);
243
+ }
244
+ //#endregion
245
+ //#region src/icons/globe-icon.tsx
246
+ /**
247
+ * Globe Icon Component.
248
+ *
249
+ * Uses Google's globe icon to match what Google Search results show for sites
250
+ * without a favicon.
251
+ *
252
+ * Accepts any standard SVG props (e.g. `width`, `height`, `className`, `style`)
253
+ * so consumers can size and style it to fit their context.
254
+ *
255
+ * @param props - Standard SVG props.
256
+ * @return The Globe SVG icon component.
257
+ */
258
+ function GlobeIcon$2(props) {
259
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
260
+ focusable: "false",
261
+ "aria-hidden": "true",
262
+ xmlns: "http://www.w3.org/2000/svg",
263
+ viewBox: "0 0 24 24",
264
+ width: "14",
265
+ height: "14",
266
+ ...props,
267
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
268
+ fill: "currentColor",
269
+ d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 17.93c-3.95-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L9 15v1c0 1.1.9 2 2 2v1.93zm6.9-2.54c-.26-.81-1-1.39-1.9-1.39h-1v-3c0-.55-.45-1-1-1H8v-2h2c.55 0 1-.45 1-1V7h2c1.1 0 2-.9 2-2v-.41c2.93 1.19 5 4.06 5 7.41 0 2.08-.8 3.97-2.1 5.39z"
270
+ })
271
+ });
272
+ }
273
+ //#endregion
274
+ //#region src/site-icon-with-fallback.tsx
275
+ /**
276
+ * Renders a default site icon: a neutral grey circle with a globe glyph,
277
+ * matching what Google's search results show for sites without a favicon.
278
+ * The wrapping span adopts the caller's `className` so the size is inherited
279
+ * from whatever rule the preview already has on that class.
280
+ *
281
+ * @param {Pick< SiteIconWithFallbackProps, 'className' >} props - The wrapper props.
282
+ * @return The DefaultSiteIcon component.
283
+ */
284
+ function DefaultSiteIcon({ className }) {
285
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
286
+ className,
287
+ "aria-hidden": "true",
288
+ style: {
289
+ display: "inline-flex",
290
+ alignItems: "center",
291
+ justifyContent: "center",
292
+ backgroundColor: "#e8eaed",
293
+ color: "#5f6368",
294
+ borderRadius: "50%"
295
+ },
296
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(GlobeIcon$2, { style: {
297
+ width: "60%",
298
+ height: "60%"
299
+ } })
300
+ });
301
+ }
302
+ /**
303
+ * Renders a site icon image with a fallback to a default globe icon if no URL
304
+ * is provided or the URL fails to load.
305
+ *
306
+ * @param {SiteIconWithFallbackProps} props - The props for the SiteIconWithFallback component.
307
+ *
308
+ * @return The SiteIconWithFallback component.
309
+ */
310
+ function SiteIconWithFallback({ src: siteIconUrl, alt = "", className, fallback = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DefaultSiteIcon, { className }) }) {
311
+ const [imageUrlWithError, setImageUrlWithError] = (0, react.useState)("");
312
+ const onError = (0, react.useCallback)((event) => {
313
+ setImageUrlWithError(event.target.src);
314
+ }, []);
315
+ return siteIconUrl && imageUrlWithError !== siteIconUrl ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
316
+ src: siteIconUrl,
317
+ alt,
318
+ onError,
319
+ className
320
+ }) : fallback;
321
+ }
322
+ //#endregion
323
+ //#region src/google-search-preview/index.tsx
324
+ const URL_LENGTH$1 = 68;
325
+ const TITLE_LENGTH$5 = 63;
326
+ const DESCRIPTION_LENGTH$3 = 160;
327
+ const googleUrl = (url) => {
328
+ const protocol = url.startsWith("https://") ? "https://" : "http://";
329
+ const breadcrumb = protocol + url.replace(protocol, "").split("/").join(" › ");
330
+ return firstValid(shortEnough(URL_LENGTH$1), hardTruncation(URL_LENGTH$1))(breadcrumb);
331
+ };
332
+ const googleTitle = firstValid(shortEnough(TITLE_LENGTH$5), truncatedAtSpace(TITLE_LENGTH$5 - 40, 73), hardTruncation(TITLE_LENGTH$5));
333
+ const googleDescription = firstValid(shortEnough(DESCRIPTION_LENGTH$3), truncatedAtSpace(DESCRIPTION_LENGTH$3 - 80, 170), hardTruncation(DESCRIPTION_LENGTH$3));
334
+ const GoogleSearchPreview = ({ description = "", siteIcon, siteTitle, title = "", url = "" }) => {
335
+ const domain = baseDomain(url);
336
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
337
+ className: "search-preview",
338
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
339
+ className: "search-preview__display",
340
+ children: [
341
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
342
+ className: "search-preview__header",
343
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
344
+ className: "search-preview__branding",
345
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SiteIconWithFallback, {
346
+ className: "search-preview__icon",
347
+ src: siteIcon
348
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
349
+ className: "search-preview__site",
350
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
351
+ className: "search-preview__site--title",
352
+ children: siteTitle || domain
353
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
354
+ className: "search-preview__url",
355
+ children: googleUrl(url)
356
+ })]
357
+ })]
358
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
359
+ className: "search-preview__menu",
360
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
361
+ focusable: "false",
362
+ xmlns: "http://www.w3.org/2000/svg",
363
+ viewBox: "0 0 24 24",
364
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z" })
365
+ })
366
+ })]
367
+ }),
368
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
369
+ className: "search-preview__title",
370
+ children: googleTitle(title)
371
+ }),
372
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
373
+ className: "search-preview__description",
374
+ children: googleDescription(stripHtmlTags(description))
375
+ })
376
+ ]
377
+ })
378
+ });
379
+ };
380
+ //#endregion
381
+ //#region src/shared/media-image/index.tsx
382
+ /**
383
+ * MediaImage
384
+ *
385
+ * A thin wrapper over `<img>` that renders an optional focal point as an inline
386
+ * `object-position`, so the visible crop (under `object-fit: cover`) keeps the
387
+ * focal point in view.
388
+ *
389
+ * The crop model is "focal point at the center of the crop, clamped to the
390
+ * image edges" — the same model image CDNs use when they generate the cropped
391
+ * share image. CSS `object-position` percentages are *alignment*, not centering
392
+ * (they only match a centered crop at 50%), so we remap the focal point into the
393
+ * `object-position` value that reproduces a centered crop. The remap needs the
394
+ * image's natural aspect ratio and the rendered box's aspect ratio, both read
395
+ * from the element itself, so callers pass only a `focalPoint`.
396
+ *
397
+ * Before those sizes are known (initial render, or a non-layout environment like
398
+ * tests) it falls back to the raw focal point; the value is corrected once the
399
+ * image loads.
400
+ */
401
+ const clamp = (value) => Math.min(Math.max(value, 0), 1);
402
+ /**
403
+ * Remaps one axis of a focal point into the `object-position` fraction that
404
+ * reproduces a centered-and-clamped crop, given that axis's overflow ratio.
405
+ *
406
+ * @param {number} focal - The focal coordinate on the overflowing axis (0-1).
407
+ * @param {number} ratio - Visible fraction of the image on that axis (boxShorter / imageLonger).
408
+ * @return {number} The object-position fraction (0-1).
409
+ */
410
+ const remapAxis = (focal, ratio) => {
411
+ if (ratio >= 1) return focal;
412
+ return clamp((focal - ratio / 2) / (1 - ratio));
413
+ };
414
+ /**
415
+ * Converts a focal point into the `object-position` point that reproduces a
416
+ * centered-and-clamped crop under `object-fit: cover`.
417
+ *
418
+ * @param {FocalPoint} focalPoint - The focal point, both axes 0-1.
419
+ * @param {number} imageAspect - The image's natural aspect ratio (w/h).
420
+ * @param {number} boxAspect - The rendered box's aspect ratio (w/h).
421
+ * @return {FocalPoint} The object-position point, both axes 0-1.
422
+ */
423
+ const focalPointToObjectPosition = (focalPoint, imageAspect, boxAspect) => {
424
+ if (imageAspect < boxAspect) return {
425
+ x: focalPoint.x,
426
+ y: remapAxis(focalPoint.y, imageAspect / boxAspect)
427
+ };
428
+ if (imageAspect > boxAspect) return {
429
+ x: remapAxis(focalPoint.x, boxAspect / imageAspect),
430
+ y: focalPoint.y
431
+ };
432
+ return focalPoint;
433
+ };
434
+ const MediaImage = ({ focalPoint, style, onLoad, ...props }) => {
435
+ const ref = (0, react.useRef)(null);
436
+ const [aspects, setAspects] = (0, react.useState)(null);
437
+ const measure = (0, react.useCallback)(() => {
438
+ const el = ref.current;
439
+ if (!el) return;
440
+ const { naturalWidth, naturalHeight, clientWidth, clientHeight } = el;
441
+ if (naturalWidth && naturalHeight && clientWidth && clientHeight) setAspects({
442
+ image: naturalWidth / naturalHeight,
443
+ box: clientWidth / clientHeight
444
+ });
445
+ }, []);
446
+ (0, react.useEffect)(() => {
447
+ measure();
448
+ const el = ref.current;
449
+ if (!el || typeof ResizeObserver === "undefined") return;
450
+ const observer = new ResizeObserver(measure);
451
+ observer.observe(el);
452
+ return () => observer.disconnect();
453
+ }, [measure]);
454
+ const handleLoad = (0, react.useCallback)((event) => {
455
+ measure();
456
+ onLoad?.(event);
457
+ }, [measure, onLoad]);
458
+ const position = focalPoint && aspects ? focalPointToObjectPosition(focalPoint, aspects.image, aspects.box) : focalPoint;
459
+ const focalPointStyle = position ? { objectPosition: `${position.x * 100}% ${position.y * 100}%` } : void 0;
460
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
461
+ ...props,
462
+ ref,
463
+ onLoad: handleLoad,
464
+ style: focalPointStyle || style ? {
465
+ ...style,
466
+ ...focalPointStyle
467
+ } : void 0
468
+ });
469
+ };
470
+ //#endregion
471
+ //#region src/twitter-preview/card.tsx
472
+ const DESCRIPTION_LENGTH$2 = 280;
473
+ const twitterDescription = firstValid(shortEnough(DESCRIPTION_LENGTH$2), hardTruncation(DESCRIPTION_LENGTH$2));
474
+ const Card$1 = ({ description, image, imageFocalPoint, title, cardType, url }) => {
475
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
476
+ className: "twitter-preview__card",
477
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
478
+ className: (0, clsx.default)(`twitter-preview__card-${cardType}`, { "twitter-preview__card-has-image": !!image }),
479
+ children: [image && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MediaImage, {
480
+ className: "twitter-preview__card-image",
481
+ src: image,
482
+ alt: "",
483
+ focalPoint: imageFocalPoint
484
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
485
+ className: "twitter-preview__card-body",
486
+ children: [
487
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
488
+ className: "twitter-preview__card-url",
489
+ children: baseDomain(url || "")
490
+ }),
491
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
492
+ className: "twitter-preview__card-title",
493
+ children: title
494
+ }),
495
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
496
+ className: "twitter-preview__card-description",
497
+ children: twitterDescription(stripHtmlTags(description))
498
+ })
499
+ ]
500
+ })]
501
+ })
502
+ });
503
+ };
504
+ //#endregion
505
+ //#region src/twitter-preview/footer.tsx
506
+ const Footer$1 = () => {
507
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
508
+ className: "twitter-preview__footer",
509
+ children: [
510
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
511
+ className: "twitter-preview__icon-replies",
512
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
513
+ viewBox: "0 0 24 24",
514
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("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.01zm8.005-6c-3.317 0-6.005 2.69-6.005 6 0 3.37 2.77 6.08 6.138 6.01l.351-.01h1.761v2.3l5.087-2.81c1.951-1.08 3.163-3.13 3.163-5.36 0-3.39-2.744-6.13-6.129-6.13H9.756z" })
515
+ })
516
+ }),
517
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
518
+ className: "twitter-preview__icon-retweets",
519
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
520
+ viewBox: "0 0 24 24",
521
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M4.5 3.88l4.432 4.14-1.364 1.46L5.5 7.55V16c0 1.1.896 2 2 2H13v2H7.5c-2.209 0-4-1.79-4-4V7.55L1.432 9.48.068 8.02 4.5 3.88zM16.5 6H11V4h5.5c2.209 0 4 1.79 4 4v8.45l2.068-1.93 1.364 1.46-4.432 4.14-4.432-4.14 1.364-1.46 2.068 1.93V8c0-1.1-.896-2-2-2z" })
522
+ })
523
+ }),
524
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
525
+ className: "twitter-preview__icon-likes",
526
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
527
+ viewBox: "0 0 24 24",
528
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M16.697 5.5c-1.222-.06-2.679.51-3.89 2.16l-.805 1.09-.806-1.09C9.984 6.01 8.526 5.44 7.304 5.5c-1.243.07-2.349.78-2.91 1.91-.552 1.12-.633 2.78.479 4.82 1.074 1.97 3.257 4.27 7.129 6.61 3.87-2.34 6.052-4.64 7.126-6.61 1.111-2.04 1.03-3.7.477-4.82-.561-1.13-1.666-1.84-2.908-1.91zm4.187 7.69c-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" })
529
+ })
530
+ }),
531
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
532
+ className: "twitter-preview__icon-analytics",
533
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
534
+ viewBox: "0 0 24 24",
535
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M8.75 21V3h2v18h-2zM18 21V8.5h2V21h-2zM4 21l.004-10h2L6 21H4zm9.248 0v-7h2v7h-2z" })
536
+ })
537
+ }),
538
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
539
+ className: "twitter-preview__icon-share",
540
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
541
+ viewBox: "0 0 24 24",
542
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M12 2.59l5.7 5.7-1.41 1.42L13 6.41V16h-2V6.41l-3.3 3.3-1.41-1.42L12 2.59zM21 15l-.02 3.51c0 1.38-1.12 2.49-2.5 2.49H5.5C4.11 21 3 19.88 3 18.5V15h2v3.5c0 .28.22.5.5.5h12.98c.28 0 .5-.22.5-.5L19 15h2z" })
543
+ })
544
+ })
545
+ ]
546
+ });
547
+ };
548
+ //#endregion
549
+ //#region src/twitter-preview/header.tsx
550
+ const Header$1 = ({ name, screenName, date }) => {
551
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
552
+ className: "twitter-preview__header",
553
+ children: [
554
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
555
+ className: "twitter-preview__name",
556
+ children: name || (0, _wordpress_i18n.__)("Account Name", "social-previews")
557
+ }),
558
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
559
+ className: "twitter-preview__screen-name",
560
+ children: screenName || "@account"
561
+ }),
562
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "·" }),
563
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
564
+ className: "twitter-preview__date",
565
+ children: formatTweetDate(date || Date.now())
566
+ })
567
+ ]
568
+ });
569
+ };
570
+ //#endregion
571
+ //#region src/twitter-preview/media.tsx
572
+ const Media$1 = ({ media }) => {
573
+ const filteredMedia = media.filter((mediaItem) => mediaItem.type.startsWith("image/") || mediaItem.type.startsWith("video/")).filter((mediaItem, idx, array) => {
574
+ if (0 === idx) return true;
575
+ if (array[0].type.startsWith("video/") || "image/gif" === array[0].type) return false;
576
+ if (mediaItem.type.startsWith("video/") || "image/gif" === mediaItem.type) return false;
577
+ return true;
578
+ }).slice(0, 4);
579
+ if (0 === filteredMedia.length) return null;
580
+ const isVideo = filteredMedia[0].type.startsWith("video/");
581
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
582
+ className: (0, clsx.default)(["twitter-preview__media", "twitter-preview__media-children-" + filteredMedia.length]),
583
+ children: filteredMedia.map((mediaItem, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react.Fragment, { children: isVideo ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("video", {
584
+ controls: true,
585
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("source", {
586
+ src: mediaItem.url,
587
+ type: mediaItem.type
588
+ })
589
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
590
+ alt: mediaItem.alt || "",
591
+ src: mediaItem.url
592
+ }) }, `twitter-preview__media-item-${index}`))
593
+ });
594
+ };
595
+ //#endregion
596
+ //#region src/twitter-preview/quote-tweet.tsx
597
+ const QuoteTweet = ({ tweetUrl }) => {
598
+ if (!tweetUrl) return null;
599
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
600
+ className: "twitter-preview__quote-tweet",
601
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_wordpress_components.SandBox, {
602
+ html: `<blockquote class="twitter-tweet" data-conversation="none" data-dnt="true"><a href="${tweetUrl}"></a></blockquote>`,
603
+ scripts: ["https://platform.twitter.com/widgets.js"],
604
+ title: "Embedded tweet"
605
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "twitter-preview__quote-tweet-overlay" })]
606
+ });
607
+ };
608
+ //#endregion
609
+ //#region src/avatar-with-fallback.tsx
610
+ /**
611
+ * Renders a default avatar SVG.
612
+ *
613
+ * @param {Pick< AvatarWithFallbackProps, 'className' >} props - The SVG props.
614
+ * @return The DefaultAvatar component.
615
+ */
616
+ function DefaultAvatar(props) {
617
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
618
+ xmlns: "http://www.w3.org/2000/svg",
619
+ viewBox: "0 0 340 340",
620
+ width: "36",
621
+ height: "36",
622
+ "aria-hidden": "true",
623
+ ...props,
624
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
625
+ fill: "#DDD",
626
+ d: "m169,.5a169,169 0 1,0 2,0zm0,86a76,76 0 1 1-2,0zM57,287q27-35 67-35h92q40,0 67,35a164,164 0 0,1-226,0"
627
+ })
628
+ });
629
+ }
630
+ /**
631
+ * Renders an avatar image with a fallback to a default avatar if no URL is provided or if the URL fails to load.
632
+ *
633
+ * @param {AvatarWithFallbackProps} props - The props for the AvatarWithFallback component.
634
+ *
635
+ * @return The AvatarWithFallback component.
636
+ */
637
+ function AvatarWithFallback({ src: avatarUrl, alt = "", className, fallback = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DefaultAvatar, { className }) }) {
638
+ const [imageUrlWithError, setImageUrlWithError] = (0, react.useState)("");
639
+ const onError = (0, react.useCallback)((event) => {
640
+ setImageUrlWithError(event.target.src);
641
+ }, []);
642
+ return !!avatarUrl && imageUrlWithError !== avatarUrl ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
643
+ src: avatarUrl,
644
+ alt,
645
+ onError,
646
+ className
647
+ }) : fallback;
648
+ }
649
+ //#endregion
650
+ //#region src/twitter-preview/sidebar.tsx
651
+ const Sidebar$1 = ({ profileImage, showThreadConnector }) => {
652
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
653
+ className: "twitter-preview__sidebar",
654
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
655
+ className: "twitter-preview__profile-image",
656
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AvatarWithFallback, { src: profileImage })
657
+ }), showThreadConnector && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "twitter-preview__connector" })]
658
+ });
659
+ };
660
+ //#endregion
661
+ //#region src/twitter-preview/text.tsx
662
+ const Text = ({ text }) => {
663
+ if (!text) return null;
664
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
665
+ className: "twitter-preview__text",
666
+ children: preparePreviewText(text, { platform: "twitter" })
667
+ });
668
+ };
669
+ //#endregion
670
+ //#region src/twitter-preview/post-preview.tsx
671
+ const TwitterPostPreview = ({ date, description, image, imageFocalPoint, media, name, profileImage, screenName, showThreadConnector, text, title, tweetUrl, cardType, url }) => {
672
+ const hasMedia = !!media?.length;
673
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
674
+ className: "twitter-preview__wrapper",
675
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
676
+ className: "twitter-preview__container",
677
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Sidebar$1, {
678
+ profileImage,
679
+ showThreadConnector
680
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
681
+ className: "twitter-preview__main",
682
+ children: [
683
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Header$1, {
684
+ name,
685
+ screenName,
686
+ date
687
+ }),
688
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
689
+ className: "twitter-preview__content",
690
+ children: [
691
+ text ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Text, { text }) : null,
692
+ hasMedia ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Media$1, { media }) : null,
693
+ tweetUrl ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(QuoteTweet, { tweetUrl }) : null,
694
+ !hasMedia && url && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Card$1, {
695
+ description: description || "",
696
+ image,
697
+ imageFocalPoint,
698
+ title: title || "",
699
+ cardType: cardType || "",
700
+ url
701
+ })
702
+ ]
703
+ }),
704
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Footer$1, {})
705
+ ]
706
+ })]
707
+ })
708
+ });
709
+ };
710
+ //#endregion
711
+ //#region src/twitter-preview/link-preview.tsx
712
+ const TwitterLinkPreview = (props) => {
713
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TwitterPostPreview, {
714
+ ...props,
715
+ text: "",
716
+ media: void 0
717
+ });
718
+ };
719
+ //#endregion
720
+ //#region src/shared/section-heading/index.tsx
721
+ const HEADING_LEVELS = [
722
+ 2,
723
+ 3,
724
+ 4,
725
+ 5,
726
+ 6
727
+ ];
728
+ const SectionHeading = ({ className, level, children }) => {
729
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(`h${level && HEADING_LEVELS.includes(level) ? level : 3}`, {
730
+ className: `social-preview__section-heading ${className ?? ""}`,
731
+ children
732
+ });
733
+ };
734
+ //#endregion
735
+ //#region src/twitter-preview/previews.tsx
736
+ const TwitterPreviews = ({ headingLevel, hideLinkPreview, hidePostPreview, tweets }) => {
737
+ if (!tweets?.length) return null;
738
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
739
+ className: "social-preview twitter-preview",
740
+ children: [!hidePostPreview && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
741
+ className: "social-preview__section twitter-preview__section",
742
+ children: [
743
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SectionHeading, {
744
+ level: headingLevel,
745
+ children: (0, _wordpress_i18n.__)("Your post", "social-previews")
746
+ }),
747
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
748
+ className: "social-preview__section-desc",
749
+ children: (0, _wordpress_i18n.__)("This is what your social post will look like on X:", "social-previews")
750
+ }),
751
+ tweets.map((tweet, index) => {
752
+ const isLast = index + 1 === tweets.length;
753
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TwitterPostPreview, {
754
+ ...tweet,
755
+ showThreadConnector: !isLast
756
+ }, `twitter-preview__tweet-${index}`);
757
+ })
758
+ ]
759
+ }), !hideLinkPreview && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
760
+ className: "social-preview__section twitter-preview__section",
761
+ children: [
762
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SectionHeading, {
763
+ level: headingLevel,
764
+ children: (0, _wordpress_i18n.__)("Link preview", "social-previews")
765
+ }),
766
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
767
+ className: "social-preview__section-desc",
768
+ children: (0, _wordpress_i18n.__)("This is what it will look like when someone shares the link to your WordPress post on X.", "social-previews")
769
+ }),
770
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TwitterLinkPreview, {
771
+ ...tweets[0],
772
+ name: "",
773
+ profileImage: "",
774
+ screenName: ""
775
+ })
776
+ ]
777
+ })]
778
+ });
779
+ };
780
+ /**
781
+ * Counts Unicode codepoints rather than UTF-16 code units, so an emoji like 🚀 is one character (matching PHP `mb_strlen`).
782
+ *
783
+ * @param text - The string to measure.
784
+ * @return The codepoint count.
785
+ */
786
+ function codepointLength(text) {
787
+ return Array.from(text).length;
788
+ }
789
+ /**
790
+ * Truncates `text` to at most `limit` codepoints, preferring the last space
791
+ * within the final 80 codepoints so we don't slice mid-word.
792
+ *
793
+ * @param text - The string to truncate.
794
+ * @param limit - Maximum codepoint length of the returned string.
795
+ * @return The truncated string (without an ellipsis).
796
+ */
797
+ function truncateAtWordBoundary(text, limit) {
798
+ const codepoints = Array.from(text);
799
+ if (codepoints.length <= limit) return text;
800
+ const slice = codepoints.slice(0, limit).join("");
801
+ const lastSpace = slice.lastIndexOf(" ");
802
+ const cut = lastSpace > limit - 80 ? lastSpace : slice.length;
803
+ return slice.slice(0, cut);
804
+ }
805
+ /**
806
+ * Wraps a body-text formatter with a "See more" / "See less" toggle when the
807
+ * input exceeds {@link EXPAND_THRESHOLD_CHARS} visible (HTML-stripped)
808
+ * characters.
809
+ *
810
+ * @param props - {@link ExpandableTextProps}.
811
+ * @return The body text node, optionally followed by a See more/See less toggle.
812
+ */
813
+ function ExpandableText(props) {
814
+ const { text, children } = props;
815
+ const [expanded, toggle] = (0, react.useReducer)((state) => !state, false);
816
+ const stripped = stripHtmlTags(text);
817
+ if (codepointLength(stripped) <= 400) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: children(text) });
818
+ if (expanded) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
819
+ children(text),
820
+ " ",
821
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_wordpress_components.Button, {
822
+ variant: "link",
823
+ className: "social-previews__expand-toggle",
824
+ onClick: toggle,
825
+ children: (0, _wordpress_i18n.__)("See less", "social-previews")
826
+ })
827
+ ] });
828
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
829
+ children(truncateAtWordBoundary(stripped, 400)),
830
+ "… ",
831
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_wordpress_components.Button, {
832
+ variant: "link",
833
+ className: "social-previews__expand-toggle",
834
+ onClick: toggle,
835
+ children: (0, _wordpress_i18n.__)("See more", "social-previews")
836
+ })
837
+ ] });
838
+ }
839
+ //#endregion
840
+ //#region src/linkedin-preview/constants.ts
841
+ const FEED_TEXT_MAX_LENGTH$2 = 3e3;
842
+ //#endregion
843
+ //#region src/linkedin-preview/post-preview.tsx
844
+ /**
845
+ * LinkedIn Post Preview Component
846
+ *
847
+ * @param {LinkedInPreviewProps} props - The props for the LinkedIn post preview.
848
+ *
849
+ * @return The LinkedIn post preview component.
850
+ */
851
+ function LinkedInPostPreview({ articleReadTime = 5, image, imageFocalPoint, jobTitle, name, profileImage, description, media, title, url }) {
852
+ const hasMedia = !!media?.length;
853
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
854
+ className: "linkedin-preview__wrapper",
855
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
856
+ className: `linkedin-preview__container ${hasMedia ? "has-media" : ""}`,
857
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
858
+ className: "linkedin-preview__header",
859
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
860
+ className: "linkedin-preview__header--avatar",
861
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AvatarWithFallback, { src: profileImage })
862
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
863
+ className: "linkedin-preview__header--profile",
864
+ children: [
865
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
866
+ className: "linkedin-preview__header--profile-info",
867
+ children: [
868
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
869
+ className: "linkedin-preview__header--profile-name",
870
+ children: name || (0, _wordpress_i18n.__)("Account Name", "social-previews")
871
+ }),
872
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "•" }),
873
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
874
+ className: "linkedin-preview__header--profile-actor",
875
+ children: (0, _wordpress_i18n.__)("1st", "social-previews")
876
+ })
877
+ ]
878
+ }),
879
+ jobTitle ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
880
+ className: "linkedin-preview__header--profile-title",
881
+ children: jobTitle
882
+ }) : null,
883
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
884
+ className: "linkedin-preview__header--profile-meta",
885
+ children: [
886
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: (0, _wordpress_i18n.__)("1h", "social-previews") }),
887
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "•" }),
888
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
889
+ viewBox: "0 0 16 16",
890
+ fill: "currentColor",
891
+ width: "16",
892
+ height: "16",
893
+ focusable: "false",
894
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M8 1a7 7 0 107 7 7 7 0 00-7-7zM3 8a5 5 0 011-3l.55.55A1.5 1.5 0 015 6.62v1.07a.75.75 0 00.22.53l.56.56a.75.75 0 00.53.22H7v.69a.75.75 0 00.22.53l.56.56a.75.75 0 01.22.53V13a5 5 0 01-5-5zm6.24 4.83l2-2.46a.75.75 0 00.09-.8l-.58-1.16A.76.76 0 0010 8H7v-.19a.51.51 0 01.28-.45l.38-.19a.74.74 0 01.68 0L9 7.5l.38-.7a1 1 0 00.12-.48v-.85a.78.78 0 01.21-.53l1.07-1.09a5 5 0 01-1.54 9z" })
895
+ })
896
+ ]
897
+ })
898
+ ]
899
+ })]
900
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
901
+ className: "linkedin-preview__content",
902
+ children: [description ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
903
+ className: "linkedin-preview__caption",
904
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ExpandableText, {
905
+ text: description,
906
+ children: (visibleText) => preparePreviewText(visibleText, {
907
+ platform: "linkedin",
908
+ maxChars: FEED_TEXT_MAX_LENGTH$2
909
+ })
910
+ }) }), hasMedia && url && !description.includes(url) && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [" - ", /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
911
+ href: url,
912
+ rel: "nofollow noopener noreferrer",
913
+ target: "_blank",
914
+ children: url
915
+ })] })]
916
+ }) : null, hasMedia ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
917
+ className: "linkedin-preview__media",
918
+ children: media.map((mediaItem, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
919
+ className: "linkedin-preview__media-item",
920
+ children: mediaItem.type.startsWith("video/") ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("video", {
921
+ controls: true,
922
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("source", {
923
+ src: mediaItem.url,
924
+ type: mediaItem.type
925
+ })
926
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
927
+ alt: mediaItem.alt || "",
928
+ src: mediaItem.url
929
+ })
930
+ }, `linkedin-preview__media-item-${index}`))
931
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("article", { children: [image ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MediaImage, {
932
+ className: "linkedin-preview__image",
933
+ src: image,
934
+ alt: "",
935
+ focalPoint: imageFocalPoint
936
+ }) : null, url ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
937
+ className: "linkedin-preview__description",
938
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
939
+ className: "linkedin-preview__description--title",
940
+ children: title || getTitleFromDescription(description)
941
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
942
+ className: "linkedin-preview__description--meta",
943
+ children: [
944
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
945
+ className: "linkedin-preview__description--url",
946
+ children: baseDomain(url)
947
+ }),
948
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "•" }),
949
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: (0, _wordpress_i18n.sprintf)((0, _wordpress_i18n.__)("%d min read", "social-previews"), articleReadTime) })
950
+ ]
951
+ })]
952
+ }) : null] })]
953
+ })]
954
+ })
955
+ });
956
+ }
957
+ //#endregion
958
+ //#region src/linkedin-preview/link-preview.tsx
959
+ /**
960
+ * LinkedIn Link Preview Component
961
+ * @param {LinkedInLinkPreviewProps} props - The props for the LinkedIn link preview.
962
+ * @return The LinkedIn link preview component.
963
+ */
964
+ function LinkedInLinkPreview(props) {
965
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LinkedInPostPreview, {
966
+ name: "",
967
+ profileImage: "",
968
+ ...props,
969
+ description: "",
970
+ media: void 0,
971
+ title: props.title || getTitleFromDescription(props.description)
972
+ });
973
+ }
974
+ //#endregion
975
+ //#region src/linkedin-preview/previews.tsx
976
+ const LinkedInPreviews = ({ headingLevel, hideLinkPreview, hidePostPreview, ...props }) => {
977
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
978
+ className: "social-preview linkedin-preview",
979
+ children: [!hidePostPreview && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
980
+ className: "social-preview__section linkedin-preview__section",
981
+ children: [
982
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SectionHeading, {
983
+ level: headingLevel,
984
+ children: (0, _wordpress_i18n.__)("Your post", "social-previews")
985
+ }),
986
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
987
+ className: "social-preview__section-desc",
988
+ children: (0, _wordpress_i18n.__)("This is what your social post will look like on LinkedIn:", "social-previews")
989
+ }),
990
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LinkedInPostPreview, { ...props })
991
+ ]
992
+ }), !hideLinkPreview && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
993
+ className: "social-preview__section linkedin-preview__section",
994
+ children: [
995
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SectionHeading, {
996
+ level: headingLevel,
997
+ children: (0, _wordpress_i18n.__)("Link preview", "social-previews")
998
+ }),
999
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1000
+ className: "social-preview__section-desc",
1001
+ children: (0, _wordpress_i18n.__)("This is what it will look like when someone shares the link to your WordPress post on LinkedIn.", "social-previews")
1002
+ }),
1003
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LinkedInLinkPreview, {
1004
+ ...props,
1005
+ name: "",
1006
+ profileImage: ""
1007
+ })
1008
+ ]
1009
+ })]
1010
+ });
1011
+ };
1012
+ //#endregion
1013
+ //#region src/tumblr-preview/helpers.ts
1014
+ const TITLE_LENGTH$4 = 1e3;
1015
+ const DESCRIPTION_LENGTH$1 = 4096;
1016
+ const tumblrTitle = (text) => firstValid(shortEnough(TITLE_LENGTH$4), hardTruncation(TITLE_LENGTH$4))(stripHtmlTags(text)) || "";
1017
+ const tumblrDescription = (text) => {
1018
+ let processedText = text;
1019
+ let startIndex = processedText.indexOf("<!--");
1020
+ while (startIndex !== -1) {
1021
+ const endIndex = processedText.indexOf("-->", startIndex);
1022
+ if (endIndex === -1) {
1023
+ processedText = processedText.substring(0, startIndex);
1024
+ break;
1025
+ }
1026
+ processedText = processedText.substring(0, startIndex) + processedText.substring(endIndex + 3);
1027
+ startIndex = processedText.indexOf("<!--");
1028
+ }
1029
+ processedText = processedText.replace(/<\/p>/g, "</p>\n\n");
1030
+ return firstValid(shortEnough(DESCRIPTION_LENGTH$1), hardTruncation(DESCRIPTION_LENGTH$1))(stripHtmlTags(processedText)) || "";
1031
+ };
1032
+ //#endregion
1033
+ //#region src/tumblr-preview/post/icons/index.tsx
1034
+ const TumblrPostIcon = ({ name }) => {
1035
+ let svg;
1036
+ switch (name) {
1037
+ case "blaze":
1038
+ svg = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
1039
+ viewBox: "0 0 25 22",
1040
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "m7.5059-0.24414c-0.79843 0.057223-1.2169 0.88587-1.1635 1.6128-0.2266 2.0449-1.4898 3.8696-3.1975 4.9778-3.0182 2.414-4.2201 6.8066-2.8033 10.411 0.92417 2.4679 2.9589 4.5674 5.4768 5.3928 0.95914 0.16102 1.7233-0.94358 1.3074-1.8059-0.11578-0.51062-0.17482-0.96516-0.17845-1.487 1.0413 1.5607 2.5484 2.8986 4.341 3.4975 1.0396-0.0154 1.98-0.64458 2.8516-1.1608 3.3821-2.1786 4.9604-6.7097 3.6597-10.518-0.49144-1.4599-1.2948-2.8935-2.5028-3.8698-0.7512-0.45498-1.661 0.09677-1.9202 0.86038-0.12274 0.16822-0.70352 1.1955-0.6191 0.61976 0.25488-3.4397-1.6789-7.0066-4.8123-8.4958-0.14322-0.037843-0.292-0.049464-0.43945-0.035156zm1.0586 3.5605c1.8947 2.0016 2.2326 5.1984 0.89062 7.5879-0.38498 0.96148 0.71762 2.0063 1.6567 1.5681 1.4159-0.4624 2.6998-1.3259 3.6577-2.4665 1.6442 2.5888 1.1465 6.2819-1.0629 8.3379-0.62378 0.60782-1.3666 1.0945-2.1754 1.4179-1.9543-0.989-3.3534-3.0966-3.5625-5.3125-0.25636-1.0253-1.81-1.2013-2.2852-0.25781-0.75058 1.3054-1.1846 2.7948-1.2305 4.3008-2.2396-1.9852-2.8468-5.4435-1.4609-8.0527 0.58926-1.239 1.651-2.13 2.724-2.9329 1.2958-1.1271 2.2791-2.62 2.7682-4.2683l0.071578 0.069832z" })
1041
+ });
1042
+ break;
1043
+ case "delete":
1044
+ svg = /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
1045
+ viewBox: "0 0 14 17",
1046
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M12 5v9c.1.7-.3 1-1 1H3c-.5 0-.9-.3-1-1V5c0-.6-.4-1-1-1-.5 0-1 .4-1 1v9.5C0 16.1 1.4 17 3 17h8c1.8 0 3-.8 3-2.5V5c0-.6-.5-1-1-1-.6 0-1 .5-1 1z" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M4 12s0 1 1 1 1-1 1-1V5c0-.5-.4-1-1-1-.5 0-1 .5-1 1v7zm4 0s0 1 1 1 1-1 1-1V5c0-.5-.4-1-1-1-.5 0-1 .5-1 1v7zm5-10c.5 0 1-.4 1-1 0-.5-.4-.9-1-1H1C.5.1 0 .5 0 1c0 .6.6 1 1.1 1H13z" })]
1047
+ });
1048
+ break;
1049
+ case "edit":
1050
+ svg = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
1051
+ viewBox: "0 0 17.6 17.6",
1052
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M5.3 13.8l-2.1.7.7-2.1L10.3 6l1.4 1.4-6.4 6.4zm6.4-9.3l-1.4-1.4-1.4 1.4-6.7 6.7-.2.5-2 5.9 3.8-1.3 2.1-.7.4-.1.3-.3 7.8-7.8c.1 0-2.7-2.9-2.7-2.9zm5.6-1.4L14.5.3c-.4-.4-1-.4-1.4 0l-1.4 1.4L15.9 6l1.4-1.4c.4-.5.4-1.1 0-1.5" })
1053
+ });
1054
+ break;
1055
+ case "share":
1056
+ svg = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
1057
+ viewBox: "0 0 24 24",
1058
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M12.6173 1.07612C12.991 0.921338 13.4211 1.00689 13.7071 1.29289L22.7071 10.2929C23.0832 10.669 23.0991 11.2736 22.7433 11.669L13.7433 21.669C13.4663 21.9767 13.0283 22.082 12.6417 21.9336C12.2552 21.7853 12 21.414 12 21V16H11.5C7.31775 16 3.92896 18.2486 2.95256 21.3044C2.80256 21.7738 2.33292 22.064 1.84598 21.9881C1.35904 21.9122 1 21.4928 1 21V18.5C1 12.3162 5.88069 7.27245 12 7.01067V2C12 1.59554 12.2436 1.2309 12.6173 1.07612ZM14 4.41421V8C14 8.55228 13.5523 9 13 9H12.5C7.64534 9 3.64117 12.6414 3.06988 17.3419C5.09636 15.2366 8.18218 14 11.5 14H13C13.5523 14 14 14.4477 14 15V18.394L20.622 11.0362L14 4.41421Z" })
1059
+ });
1060
+ break;
1061
+ case "reply":
1062
+ svg = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
1063
+ viewBox: "0 0 17 17",
1064
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M8.7 0C4.1 0 .4 3.7.4 8.3c0 1.2.2 2.3.7 3.4-.2.6-.4 1.5-.7 2.5L0 15.8c-.2.7.5 1.4 1.2 1.2l1.6-.4 2.4-.7c1.1.5 2.2.7 3.4.7 4.6 0 8.3-3.7 8.3-8.3C17 3.7 13.3 0 8.7 0zM15 8.3c0 3.5-2.8 6.3-6.4 6.3-1.2 0-2.3-.3-3.2-.9l-3.2.9.9-3.2c-.5-.9-.9-2-.9-3.2.1-3.4 3-6.2 6.5-6.2S15 4.8 15 8.3z" })
1065
+ });
1066
+ break;
1067
+ case "reblog":
1068
+ svg = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
1069
+ viewBox: "0 0 17 18.1",
1070
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M12.8.2c-.4-.4-.8-.2-.8.4v2H2c-2 0-2 2-2 2v5s0 1 1 1 1-1 1-1v-4c0-1 .5-1 1-1h9v2c0 .6.3.7.8.4L17 3.6 12.8.2zM4.2 17.9c.5.4.8.2.8-.3v-2h10c2 0 2-2 2-2v-5s0-1-1-1-1 1-1 1v4c0 1-.5 1-1 1H5v-2c0-.6-.3-.7-.8-.4L0 14.6l4.2 3.3z" })
1071
+ });
1072
+ break;
1073
+ case "like":
1074
+ svg = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
1075
+ viewBox: "0 0 20 18",
1076
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M14.658 0c-1.625 0-3.21.767-4.463 2.156-.06.064-.127.138-.197.225-.074-.085-.137-.159-.196-.225C8.547.766 6.966 0 5.35 0 4.215 0 3.114.387 2.162 1.117c-2.773 2.13-2.611 5.89-1.017 8.5 2.158 3.535 6.556 7.18 7.416 7.875A2.3 2.3 0 0 0 9.998 18c.519 0 1.028-.18 1.436-.508.859-.695 5.257-4.34 7.416-7.875 1.595-2.616 1.765-6.376-1-8.5C16.895.387 15.792 0 14.657 0h.001zm0 2.124c.645 0 1.298.208 1.916.683 1.903 1.461 1.457 4.099.484 5.695-1.973 3.23-6.16 6.7-6.94 7.331a.191.191 0 0 1-.241 0c-.779-.631-4.966-4.101-6.94-7.332-.972-1.595-1.4-4.233.5-5.694.619-.475 1.27-.683 1.911-.683 1.064 0 2.095.574 2.898 1.461.495.549 1.658 2.082 1.753 2.203.095-.12 1.259-1.654 1.752-2.203.8-.887 1.842-1.461 2.908-1.461h-.001z" })
1077
+ });
1078
+ break;
1079
+ case "ellipsis":
1080
+ svg = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
1081
+ viewBox: "0 0 17.5 3.9",
1082
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M17.5 1.9c0 1.1-.9 1.9-1.9 1.9-1.1 0-1.9-.9-1.9-1.9S14.5 0 15.6 0c1 0 1.9.9 1.9 1.9m-6.8 0c0 1.1-.9 1.9-1.9 1.9-1.1.1-2-.8-2-1.9 0-1 .9-1.9 2-1.9s1.9.9 1.9 1.9m-6.8 0c0 1.1-.9 2-2 2-1 0-1.9-.9-1.9-2S.9 0 1.9 0c1.1 0 2 .9 2 1.9" })
1083
+ });
1084
+ break;
1085
+ }
1086
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1087
+ className: `tumblr-preview__post-icon tumblr-preview__post-icon-${name}`,
1088
+ children: svg
1089
+ });
1090
+ };
1091
+ //#endregion
1092
+ //#region src/tumblr-preview/post/actions/index.tsx
1093
+ const TumblrPostActions = () => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1094
+ className: "tumblr-preview__post-actions",
1095
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1096
+ className: "tumblr-preview__post-manage-actions",
1097
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1098
+ className: "tumblr-preview__post-actions-blaze",
1099
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(TumblrPostIcon, { name: "blaze" }), "\xA0Blaze"]
1100
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", { children: [{
1101
+ icon: "delete",
1102
+ label: (0, _wordpress_i18n.__)("Delete", "social-previews")
1103
+ }, {
1104
+ icon: "edit",
1105
+ label: (0, _wordpress_i18n.__)("Edit", "social-previews")
1106
+ }].map(({ icon, label }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", {
1107
+ "aria-label": label,
1108
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TumblrPostIcon, { name: icon })
1109
+ }, icon)) })]
1110
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1111
+ className: "tumblr-preview__post-social-actions",
1112
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: (0, _wordpress_i18n.__)("0 notes", "social-previews") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", { children: [
1113
+ {
1114
+ icon: "share",
1115
+ label: (0, _wordpress_i18n.__)("Share", "social-previews")
1116
+ },
1117
+ {
1118
+ icon: "reply",
1119
+ label: (0, _wordpress_i18n.__)("Reply", "social-previews")
1120
+ },
1121
+ {
1122
+ icon: "reblog",
1123
+ label: (0, _wordpress_i18n.__)("Reblog", "social-previews")
1124
+ },
1125
+ {
1126
+ icon: "like",
1127
+ label: (0, _wordpress_i18n.__)("Like", "social-previews")
1128
+ }
1129
+ ].map(({ icon, label }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", {
1130
+ "aria-label": label,
1131
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TumblrPostIcon, { name: icon })
1132
+ }, icon)) })]
1133
+ })]
1134
+ });
1135
+ //#endregion
1136
+ //#region src/tumblr-preview/post/header/index.tsx
1137
+ const TumblrPostHeader = ({ user }) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1138
+ className: "tumblr-preview__post-header",
1139
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1140
+ className: "tumblr-preview__post-header-username",
1141
+ children: user?.displayName || (0, _wordpress_i18n.__)("anonymous-user", "social-previews")
1142
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TumblrPostIcon, { name: "ellipsis" })]
1143
+ });
1144
+ //#endregion
1145
+ //#region src/tumblr-preview/link-preview.tsx
1146
+ const TumblrLinkPreview = ({ title, description, image, user, url, imageFocalPoint }) => {
1147
+ const avatarUrl = user?.avatarUrl;
1148
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1149
+ className: "tumblr-preview__post",
1150
+ children: [avatarUrl && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
1151
+ className: "tumblr-preview__avatar",
1152
+ src: avatarUrl,
1153
+ alt: ""
1154
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1155
+ className: "tumblr-preview__card",
1156
+ children: [
1157
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TumblrPostHeader, { user }),
1158
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1159
+ className: "tumblr-preview__window",
1160
+ children: [image && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1161
+ className: "tumblr-preview__window-top",
1162
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1163
+ className: "tumblr-preview__overlay",
1164
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1165
+ className: "tumblr-preview__title",
1166
+ children: tumblrTitle(title)
1167
+ })
1168
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MediaImage, {
1169
+ className: "tumblr-preview__image",
1170
+ src: image,
1171
+ alt: (0, _wordpress_i18n.__)("Tumblr preview thumbnail", "social-previews"),
1172
+ focalPoint: imageFocalPoint
1173
+ })]
1174
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1175
+ className: `tumblr-preview__window-bottom ${!image ? "is-full" : ""}`,
1176
+ children: [
1177
+ !image && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1178
+ className: "tumblr-preview__title",
1179
+ children: tumblrTitle(title)
1180
+ }),
1181
+ description && image && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1182
+ className: "tumblr-preview__description",
1183
+ children: tumblrDescription(description)
1184
+ }),
1185
+ url && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1186
+ className: "tumblr-preview__site-name",
1187
+ children: baseDomain(url)
1188
+ })
1189
+ ]
1190
+ })]
1191
+ }),
1192
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TumblrPostActions, {})
1193
+ ]
1194
+ })]
1195
+ });
1196
+ };
1197
+ //#endregion
1198
+ //#region src/tumblr-preview/post-preview.tsx
1199
+ const TumblrPostPreview = ({ title, description, image, user, url, media, hyperlinks, imageFocalPoint }) => {
1200
+ const avatarUrl = user?.avatarUrl;
1201
+ const mediaItem = media?.[0];
1202
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1203
+ className: "tumblr-preview__post",
1204
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(AvatarWithFallback, {
1205
+ className: "tumblr-preview__avatar",
1206
+ src: avatarUrl
1207
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1208
+ className: "tumblr-preview__card",
1209
+ children: [
1210
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TumblrPostHeader, { user }),
1211
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1212
+ className: "tumblr-preview__body",
1213
+ children: [
1214
+ title ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1215
+ className: "tumblr-preview__title",
1216
+ children: tumblrTitle(title)
1217
+ }) : null,
1218
+ description && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1219
+ className: "tumblr-preview__description",
1220
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ExpandableText, {
1221
+ text: description,
1222
+ children: (visibleText) => preparePreviewText(tumblrDescription(visibleText), {
1223
+ platform: "tumblr",
1224
+ hyperlinks
1225
+ })
1226
+ })
1227
+ }),
1228
+ mediaItem ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1229
+ className: "tumblr-preview__media-item",
1230
+ children: mediaItem.type.startsWith("video/") ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("video", {
1231
+ controls: true,
1232
+ className: "tumblr-preview__media--video",
1233
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("source", {
1234
+ src: mediaItem.url,
1235
+ type: mediaItem.type
1236
+ })
1237
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
1238
+ className: "tumblr-preview__image",
1239
+ src: mediaItem.url,
1240
+ alt: ""
1241
+ })
1242
+ }) : image && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MediaImage, {
1243
+ className: "tumblr-preview__image",
1244
+ src: image,
1245
+ alt: (0, _wordpress_i18n.__)("Tumblr preview thumbnail", "social-previews"),
1246
+ focalPoint: imageFocalPoint
1247
+ }),
1248
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
1249
+ className: "tumblr-preview__url",
1250
+ href: url,
1251
+ target: "_blank",
1252
+ rel: "noreferrer",
1253
+ children: (0, _wordpress_i18n.__)("View On WordPress", "social-previews")
1254
+ })
1255
+ ]
1256
+ }),
1257
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TumblrPostActions, {})
1258
+ ]
1259
+ })]
1260
+ });
1261
+ };
1262
+ //#endregion
1263
+ //#region src/tumblr-preview/previews.tsx
1264
+ const TumblrPreviews = ({ headingLevel, hideLinkPreview, hidePostPreview, ...props }) => {
1265
+ const hasMedia = !!props.media?.length;
1266
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1267
+ className: "social-preview tumblr-preview",
1268
+ children: [!hidePostPreview && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
1269
+ className: "social-preview__section tumblr-preview__section",
1270
+ children: [
1271
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SectionHeading, {
1272
+ level: headingLevel,
1273
+ children: (0, _wordpress_i18n.__)("Your post", "social-previews")
1274
+ }),
1275
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1276
+ className: "social-preview__section-desc",
1277
+ children: (0, _wordpress_i18n.__)("This is what your social post will look like on Tumblr:", "social-previews")
1278
+ }),
1279
+ hasMedia ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TumblrPostPreview, { ...props }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TumblrLinkPreview, { ...props })
1280
+ ]
1281
+ }), !hideLinkPreview && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
1282
+ className: "social-preview__section tumblr-preview__section",
1283
+ children: [
1284
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SectionHeading, {
1285
+ level: headingLevel,
1286
+ children: (0, _wordpress_i18n.__)("Link preview", "social-previews")
1287
+ }),
1288
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1289
+ className: "social-preview__section-desc",
1290
+ children: (0, _wordpress_i18n.__)("This is what it will look like when someone shares the link to your WordPress post on Tumblr.", "social-previews")
1291
+ }),
1292
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TumblrLinkPreview, {
1293
+ ...props,
1294
+ user: void 0
1295
+ })
1296
+ ]
1297
+ })]
1298
+ });
1299
+ };
1300
+ //#endregion
1301
+ //#region src/constants.ts
1302
+ const AUTO_SHARED_SOCIAL_POST_PREVIEW = "AUTO_SHARED_SOCIAL_POST_PREVIEW";
1303
+ const AUTO_SHARED_LINK_PREVIEW = "AUTO_SHARED_LINK_PREVIEW";
1304
+ const DEFAULT_LINK_PREVIEW = "DEFAULT_LINK_PREVIEW";
1305
+ const TYPE_WEBSITE = "website";
1306
+ const TYPE_ARTICLE = "article";
1307
+ const LANDSCAPE_MODE = "landscape";
1308
+ const PORTRAIT_MODE = "portrait";
1309
+ //#endregion
1310
+ //#region src/facebook-preview/helpers.ts
1311
+ const TITLE_LENGTH$3 = 110;
1312
+ const DESCRIPTION_LENGTH = 200;
1313
+ const CUSTOM_TEXT_LENGTH = 63206;
1314
+ const facebookTitle = (text) => firstValid(shortEnough(TITLE_LENGTH$3), hardTruncation(TITLE_LENGTH$3))(stripHtmlTags(text)) || "";
1315
+ const facebookDescription = (text) => firstValid(shortEnough(DESCRIPTION_LENGTH), hardTruncation(DESCRIPTION_LENGTH))(stripHtmlTags(text)) || "";
1316
+ //#endregion
1317
+ //#region src/facebook-preview/custom-text.tsx
1318
+ const CustomText = ({ text, url, forceUrlDisplay }) => {
1319
+ let postLink;
1320
+ if (hasTag(text, "a") || forceUrlDisplay && !!url && !text.includes(url)) postLink = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
1321
+ className: "facebook-preview__custom-text-post-url",
1322
+ href: url,
1323
+ rel: "nofollow noopener noreferrer",
1324
+ target: "_blank",
1325
+ children: url
1326
+ });
1327
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
1328
+ className: "facebook-preview__custom-text",
1329
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ExpandableText, {
1330
+ text,
1331
+ children: (visibleText) => preparePreviewText(visibleText, {
1332
+ platform: "facebook",
1333
+ maxChars: CUSTOM_TEXT_LENGTH
1334
+ })
1335
+ }) }), postLink]
1336
+ });
1337
+ };
1338
+ //#endregion
1339
+ //#region src/facebook-preview/hooks/use-image-hook.ts
1340
+ const useImage = ({ mode: initialMode }) => {
1341
+ const [mode, setMode] = (0, react.useState)(initialMode);
1342
+ const [isLoadingImage, setLoadingImage] = (0, react.useState)(true);
1343
+ const onLoad = (0, react.useCallback)(({ target }) => {
1344
+ if (!mode) {
1345
+ const image = target;
1346
+ setMode(image.naturalWidth > image.naturalHeight ? LANDSCAPE_MODE : PORTRAIT_MODE);
1347
+ }
1348
+ setLoadingImage(false);
1349
+ }, [mode]);
1350
+ const onError = (0, react.useCallback)(() => setLoadingImage(false), []);
1351
+ return [
1352
+ mode,
1353
+ isLoadingImage,
1354
+ {
1355
+ alt: (0, _wordpress_i18n.__)("Facebook Preview Thumbnail", "social-previews"),
1356
+ onLoad,
1357
+ onError
1358
+ }
1359
+ ];
1360
+ };
1361
+ //#endregion
1362
+ //#region src/facebook-preview/post/icons/index.tsx
1363
+ const FacebookPostIcon = ({ name }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("i", { className: `facebook-preview__post-icon facebook-preview__post-icon-${name}` });
1364
+ //#endregion
1365
+ //#region src/facebook-preview/post/actions/index.tsx
1366
+ const FacebookPostActions = () => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
1367
+ className: "facebook-preview__post-actions",
1368
+ children: [
1369
+ {
1370
+ icon: "like",
1371
+ label: (0, _wordpress_i18n.__)("Like", "social-previews")
1372
+ },
1373
+ {
1374
+ icon: "comment",
1375
+ label: (0, _wordpress_i18n.__)("Comment", "social-previews")
1376
+ },
1377
+ {
1378
+ icon: "share",
1379
+ label: (0, _wordpress_i18n.__)("Share", "social-previews")
1380
+ }
1381
+ ].map(({ icon, label }) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(FacebookPostIcon, { name: icon }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: label })] }, icon))
1382
+ });
1383
+ //#endregion
1384
+ //#region src/facebook-preview/post/header/index.tsx
1385
+ const FacebookPostHeader = ({ user, timeElapsed, hideOptions }) => {
1386
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1387
+ className: "facebook-preview__post-header",
1388
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1389
+ className: "facebook-preview__post-header-content",
1390
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(AvatarWithFallback, {
1391
+ className: "facebook-preview__post-header-avatar",
1392
+ src: user?.avatarUrl
1393
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1394
+ className: "facebook-preview__post-header-name",
1395
+ children: user?.displayName || (0, _wordpress_i18n.__)("Anonymous User", "social-previews")
1396
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1397
+ className: "facebook-preview__post-header-share",
1398
+ children: [
1399
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1400
+ className: "facebook-preview__post-header-time",
1401
+ children: timeElapsed ? (0, _wordpress_i18n.__)("1h", "social-previews") : (0, _wordpress_i18n._x)("Just now", "", "social-previews")
1402
+ }),
1403
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1404
+ className: "facebook-preview__post-header-dot",
1405
+ "aria-hidden": "true",
1406
+ children: "·"
1407
+ }),
1408
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FacebookPostIcon, { name: "public" })
1409
+ ]
1410
+ })] })]
1411
+ }), !hideOptions && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "facebook-preview__post-header-more" })]
1412
+ });
1413
+ };
1414
+ //#endregion
1415
+ //#region src/facebook-preview/link-preview.tsx
1416
+ const FacebookLinkPreview = ({ url, title, description, image, imageFocalPoint, user, customText, type, imageMode, compactDescription }) => {
1417
+ const [mode, isLoadingImage, imgProps] = useImage({ mode: imageMode });
1418
+ const isArticle = type === TYPE_ARTICLE;
1419
+ const modeClass = `is-${isArticle && !image || mode === "portrait" ? "portrait" : "landscape"}`;
1420
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1421
+ className: "facebook-preview__post",
1422
+ children: [
1423
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FacebookPostHeader, { user }),
1424
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1425
+ className: "facebook-preview__content",
1426
+ children: [customText && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CustomText, {
1427
+ text: customText,
1428
+ url
1429
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1430
+ className: `facebook-preview__body ${modeClass} ${image && isLoadingImage ? "is-loading" : ""}`,
1431
+ children: [(image || isArticle) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1432
+ className: `facebook-preview__image ${image ? "" : "is-empty"} ${modeClass}`,
1433
+ children: image && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MediaImage, {
1434
+ src: image,
1435
+ focalPoint: imageFocalPoint,
1436
+ ...imgProps
1437
+ })
1438
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1439
+ className: "facebook-preview__text",
1440
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1441
+ className: "facebook-preview__text-wrapper",
1442
+ children: [
1443
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1444
+ className: "facebook-preview__url",
1445
+ children: baseDomain(url)
1446
+ }),
1447
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1448
+ className: "facebook-preview__title",
1449
+ children: facebookTitle(title) || baseDomain(url)
1450
+ }),
1451
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1452
+ className: `facebook-preview__description ${compactDescription ? "is-compact" : ""}`,
1453
+ children: [description && facebookDescription(description), isArticle && !description && (0, _wordpress_i18n.__)("Visit the post for more.", "social-previews")]
1454
+ }),
1455
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1456
+ className: "facebook-preview__info",
1457
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FacebookPostIcon, { name: "info" })
1458
+ })
1459
+ ]
1460
+ })
1461
+ })]
1462
+ })]
1463
+ }),
1464
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FacebookPostActions, {})
1465
+ ]
1466
+ });
1467
+ };
1468
+ //#endregion
1469
+ //#region src/facebook-preview/link-preview-details.tsx
1470
+ const LinkPreviewDetails = ({ url, customImage, imageFocalPoint, user, customText, imageMode }) => {
1471
+ const [mode, isLoadingImage, imgProps] = useImage({ mode: imageMode });
1472
+ const modeClass = `is-${mode === "portrait" ? "portrait" : "landscape"}`;
1473
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1474
+ className: "facebook-preview__post",
1475
+ children: [
1476
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FacebookPostHeader, { user: void 0 }),
1477
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1478
+ className: "facebook-preview__content",
1479
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1480
+ className: `facebook-preview__window ${modeClass} ${customImage && isLoadingImage ? "is-loading" : ""}`,
1481
+ children: [
1482
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1483
+ className: `facebook-preview__custom-image ${modeClass}`,
1484
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MediaImage, {
1485
+ src: customImage,
1486
+ focalPoint: imageFocalPoint,
1487
+ ...imgProps
1488
+ })
1489
+ }),
1490
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FacebookPostHeader, {
1491
+ user,
1492
+ timeElapsed: true,
1493
+ hideOptions: true
1494
+ }),
1495
+ customText && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CustomText, {
1496
+ text: customText,
1497
+ url,
1498
+ forceUrlDisplay: true
1499
+ })
1500
+ ]
1501
+ })
1502
+ }),
1503
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FacebookPostActions, {})
1504
+ ]
1505
+ });
1506
+ };
1507
+ //#endregion
1508
+ //#region src/facebook-preview/post-preview.tsx
1509
+ const FacebookPostPreview = ({ url, user, customText, media, imageMode }) => {
1510
+ const [mode] = useImage({ mode: imageMode });
1511
+ const modeClass = `is-${mode === "portrait" ? "portrait" : "landscape"}`;
1512
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1513
+ className: "facebook-preview__post",
1514
+ children: [
1515
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FacebookPostHeader, { user }),
1516
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1517
+ className: "facebook-preview__content",
1518
+ children: [customText && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CustomText, {
1519
+ text: customText,
1520
+ url
1521
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1522
+ className: "facebook-preview__body",
1523
+ children: media ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1524
+ className: `facebook-preview__media ${modeClass}`,
1525
+ children: media.map((mediaItem, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1526
+ className: `facebook-preview__media-item ${modeClass}`,
1527
+ children: mediaItem.type.startsWith("video/") ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("video", {
1528
+ controls: true,
1529
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("source", {
1530
+ src: mediaItem.url,
1531
+ type: mediaItem.type
1532
+ })
1533
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
1534
+ alt: mediaItem.alt || "",
1535
+ src: mediaItem.url
1536
+ })
1537
+ }, `facebook-preview__media-item-${index}`))
1538
+ }) : null
1539
+ })]
1540
+ }),
1541
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FacebookPostActions, {})
1542
+ ]
1543
+ });
1544
+ };
1545
+ //#endregion
1546
+ //#region src/facebook-preview/previews.tsx
1547
+ const FacebookPreviews = ({ headingLevel, hideLinkPreview, hidePostPreview, ...props }) => {
1548
+ const hasMedia = !!props.media?.length;
1549
+ const hasCustomImage = !!props.customImage;
1550
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1551
+ className: "social-preview facebook-preview",
1552
+ children: [!hidePostPreview && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
1553
+ className: "social-preview__section facebook-preview__section",
1554
+ children: [
1555
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SectionHeading, {
1556
+ level: headingLevel,
1557
+ children: (0, _wordpress_i18n.__)("Your post", "social-previews")
1558
+ }),
1559
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1560
+ className: "social-preview__section-desc",
1561
+ children: (0, _wordpress_i18n.__)("This is what your social post will look like on Facebook:", "social-previews")
1562
+ }),
1563
+ hasMedia ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FacebookPostPreview, { ...props }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FacebookLinkPreview, { ...props })
1564
+ ]
1565
+ }), !hideLinkPreview && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
1566
+ className: "social-preview__section facebook-preview__section",
1567
+ children: [
1568
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SectionHeading, {
1569
+ level: headingLevel,
1570
+ children: (0, _wordpress_i18n.__)("Link preview", "social-previews")
1571
+ }),
1572
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1573
+ className: "social-preview__section-desc",
1574
+ children: (0, _wordpress_i18n.__)("This is what it will look like when someone shares the link to your WordPress post on Facebook.", "social-previews")
1575
+ }),
1576
+ hasCustomImage ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LinkPreviewDetails, { ...props }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FacebookLinkPreview, {
1577
+ ...props,
1578
+ compactDescription: true,
1579
+ customText: "",
1580
+ user: void 0
1581
+ })
1582
+ ]
1583
+ })]
1584
+ });
1585
+ };
1586
+ //#endregion
1587
+ //#region src/mastodon-preview/post/actions/index.tsx
1588
+ const MastodonPostActions = () => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1589
+ className: "mastodon-preview__post-actions",
1590
+ children: [
1591
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [
1592
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
1593
+ xmlns: "http://www.w3.org/2000/svg",
1594
+ height: "24",
1595
+ viewBox: "0 -960 960 960",
1596
+ width: "24",
1597
+ "aria-hidden": "true",
1598
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M760-200v-160q0-50-35-85t-85-35H273l144 144-57 56-240-240 240-240 57 56-144 144h367q83 0 141.5 58.5T840-360v160h-80Z" })
1599
+ }),
1600
+ "\xA0",
1601
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: 0 })
1602
+ ] }),
1603
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
1604
+ xmlns: "http://www.w3.org/2000/svg",
1605
+ height: "24",
1606
+ viewBox: "0 -960 960 960",
1607
+ width: "24",
1608
+ "aria-hidden": "true",
1609
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M280-80 120-240l160-160 56 58-62 62h406v-160h80v240H274l62 62-56 58Zm-80-440v-240h486l-62-62 56-58 160 160-160 160-56-58 62-62H280v160h-80Z" })
1610
+ }) }),
1611
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
1612
+ xmlns: "http://www.w3.org/2000/svg",
1613
+ height: "24",
1614
+ viewBox: "0 -960 960 960",
1615
+ width: "24",
1616
+ "aria-hidden": "true",
1617
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "m354-287 126-76 126 77-33-144 111-96-146-13-58-136-58 135-146 13 111 97-33 143ZM233-120l65-281L80-590l288-25 112-265 112 265 288 25-218 189 65 281-247-149-247 149Zm247-350Z" })
1618
+ }) }),
1619
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
1620
+ xmlns: "http://www.w3.org/2000/svg",
1621
+ height: "24",
1622
+ viewBox: "0 -960 960 960",
1623
+ width: "24",
1624
+ "aria-hidden": "true",
1625
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M200-120v-640q0-33 23.5-56.5T280-840h400q33 0 56.5 23.5T760-760v640L480-240 200-120Zm80-122 200-86 200 86v-518H280v518Zm0-518h400-400Z" })
1626
+ }) }),
1627
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
1628
+ xmlns: "http://www.w3.org/2000/svg",
1629
+ height: "24",
1630
+ viewBox: "0 -960 960 960",
1631
+ width: "24",
1632
+ "aria-hidden": "true",
1633
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M240-400q-33 0-56.5-23.5T160-480q0-33 23.5-56.5T240-560q33 0 56.5 23.5T320-480q0 33-23.5 56.5T240-400Zm240 0q-33 0-56.5-23.5T400-480q0-33 23.5-56.5T480-560q33 0 56.5 23.5T560-480q0 33-23.5 56.5T480-400Zm240 0q-33 0-56.5-23.5T640-480q0-33 23.5-56.5T720-560q33 0 56.5 23.5T800-480q0 33-23.5 56.5T720-400Z" })
1634
+ }) })
1635
+ ]
1636
+ });
1637
+ //#endregion
1638
+ //#region src/mastodon-preview/helpers.ts
1639
+ const TITLE_LENGTH$2 = 200;
1640
+ const BODY_LENGTH$1 = 500;
1641
+ const ADDRESS_PATTERN = /^@([^@]*)@([^@]*)$/i;
1642
+ const mastodonTitle = (text) => firstValid(shortEnough(TITLE_LENGTH$2), hardTruncation(TITLE_LENGTH$2))(stripHtmlTags(text)) || "";
1643
+ const mastodonBody = (text, options) => {
1644
+ const { instance, offset } = options;
1645
+ return preparePreviewText(text, {
1646
+ platform: "mastodon",
1647
+ maxChars: BODY_LENGTH$1 - offset,
1648
+ hashtagDomain: instance
1649
+ });
1650
+ };
1651
+ const getMastodonAddressDetails = (address) => {
1652
+ const matches = address.match(ADDRESS_PATTERN);
1653
+ return {
1654
+ username: matches?.[1] || "",
1655
+ instance: matches?.[2] || "mastodon.social"
1656
+ };
1657
+ };
1658
+ //#endregion
1659
+ //#region src/mastodon-preview/post/card/index.tsx
1660
+ const MastodonPostCard = ({ siteName, title, description, url, image, customImage, imageFocalPoint }) => {
1661
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1662
+ className: (0, clsx.default)("mastodon-preview__card", { "has-image": image }),
1663
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1664
+ className: "mastodon-preview__card-img",
1665
+ children: image || customImage ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MediaImage, {
1666
+ src: image || customImage,
1667
+ alt: (0, _wordpress_i18n.__)("Mastodon preview thumbnail", "social-previews"),
1668
+ focalPoint: imageFocalPoint
1669
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1670
+ className: "mastodon-preview__card-img--fallback",
1671
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
1672
+ xmlns: "http://www.w3.org/2000/svg",
1673
+ height: "24",
1674
+ viewBox: "0 -960 960 960",
1675
+ width: "24",
1676
+ "aria-hidden": "true",
1677
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M320-240h320v-80H320v80Zm0-160h320v-80H320v80ZM240-80q-33 0-56.5-23.5T160-160v-640q0-33 23.5-56.5T240-880h320l240 240v480q0 33-23.5 56.5T720-80H240Zm280-520h200L520-800v200Z" })
1678
+ })
1679
+ })
1680
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1681
+ className: "mastodon-preview__card-text",
1682
+ children: [
1683
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1684
+ className: "mastodon-preview__card-site",
1685
+ children: siteName || baseDomain(url)
1686
+ }),
1687
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1688
+ className: "mastodon-preview__card-title",
1689
+ children: mastodonTitle(title) || getTitleFromDescription(description)
1690
+ }),
1691
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1692
+ className: "mastodon-preview__card-description",
1693
+ children: stripHtmlTags(description)
1694
+ })
1695
+ ]
1696
+ })]
1697
+ });
1698
+ };
1699
+ //#endregion
1700
+ //#region src/mastodon-preview/post/icons/index.tsx
1701
+ /**
1702
+ * Globe Icon Component
1703
+ *
1704
+ * @return The Globe SVG icon component.
1705
+ */
1706
+ function GlobeIcon$1() {
1707
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
1708
+ xmlns: "http://www.w3.org/2000/svg",
1709
+ height: "15",
1710
+ viewBox: "0 -960 960 960",
1711
+ width: "15",
1712
+ role: "img",
1713
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M480-80q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm-40-82v-78q-33 0-56.5-23.5T360-320v-40L168-552q-3 18-5.5 36t-2.5 36q0 121 79.5 212T440-162Zm276-102q20-22 36-47.5t26.5-53q10.5-27.5 16-56.5t5.5-59q0-98-54.5-179T600-776v16q0 33-23.5 56.5T520-680h-80v80q0 17-11.5 28.5T400-560h-80v80h240q17 0 28.5 11.5T600-440v120h40q26 0 47 15.5t29 40.5Z" })
1714
+ });
1715
+ }
1716
+ //#endregion
1717
+ //#region src/mastodon-preview/post/header/index.tsx
1718
+ const MastodonPostHeader = ({ user }) => {
1719
+ const { displayName, address, avatarUrl } = user || {};
1720
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1721
+ className: "mastodon-preview__post-header",
1722
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1723
+ className: "mastodon-preview__post-header-user",
1724
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(AvatarWithFallback, {
1725
+ className: "mastodon-preview__post-avatar",
1726
+ src: avatarUrl
1727
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1728
+ className: "mastodon-preview__post-header-displayname",
1729
+ children: displayName || (0, _wordpress_i18n.__)("anonymous-user", "social-previews")
1730
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1731
+ className: "mastodon-preview__post-header-username",
1732
+ children: address?.replace(`@mastodon.social`, "") || "@username"
1733
+ })] })]
1734
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1735
+ className: "mastodon-preview__post-header-audience",
1736
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(GlobeIcon$1, {}), formatMastodonDate(/* @__PURE__ */ new Date())]
1737
+ })]
1738
+ });
1739
+ };
1740
+ //#endregion
1741
+ //#region src/mastodon-preview/link-preview.tsx
1742
+ const MastodonLinkPreview = (props) => {
1743
+ const { user } = props;
1744
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1745
+ className: "mastodon-preview__post",
1746
+ children: [
1747
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MastodonPostHeader, { user }),
1748
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MastodonPostCard, {
1749
+ ...props,
1750
+ customImage: ""
1751
+ }),
1752
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MastodonPostActions, {})
1753
+ ]
1754
+ });
1755
+ };
1756
+ //#endregion
1757
+ //#region src/mastodon-preview/post/body/index.tsx
1758
+ const MastonPostBody = (props) => {
1759
+ const { title, description, customText, user, children } = props;
1760
+ const options = {
1761
+ instance: user?.address ? getMastodonAddressDetails(user.address).instance : "",
1762
+ offset: 0
1763
+ };
1764
+ let bodyTxt;
1765
+ if (customText) bodyTxt = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ExpandableText, {
1766
+ text: customText,
1767
+ children: (visibleText) => mastodonBody(visibleText, options)
1768
+ }) });
1769
+ else if (description) if (title) {
1770
+ const renderedTitle = stripHtmlTags(title);
1771
+ options.offset = renderedTitle.length;
1772
+ bodyTxt = /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: renderedTitle }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ExpandableText, {
1773
+ text: description,
1774
+ children: (visibleText) => mastodonBody(visibleText, options)
1775
+ }) })] });
1776
+ } else bodyTxt = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ExpandableText, {
1777
+ text: description,
1778
+ children: (visibleText) => mastodonBody(visibleText, options)
1779
+ }) });
1780
+ else bodyTxt = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: mastodonBody(title, options) });
1781
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1782
+ className: "mastodon-preview__body",
1783
+ children: [bodyTxt, children]
1784
+ });
1785
+ };
1786
+ //#endregion
1787
+ //#region src/mastodon-preview/post-preview.tsx
1788
+ const MastodonPostPreview = (props) => {
1789
+ const { user, media } = props;
1790
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1791
+ className: "mastodon-preview__post",
1792
+ children: [
1793
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MastodonPostHeader, { user }),
1794
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MastonPostBody, {
1795
+ ...props,
1796
+ children: media?.length ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1797
+ className: (0, clsx.default)("mastodon-preview__media", { "as-grid": media.length > 1 }),
1798
+ children: media.map((mediaItem, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1799
+ className: "mastodon-preview__media-item",
1800
+ children: mediaItem.type.startsWith("video/") ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("video", {
1801
+ controls: true,
1802
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("source", {
1803
+ src: mediaItem.url,
1804
+ type: mediaItem.type
1805
+ })
1806
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
1807
+ alt: mediaItem.alt || "",
1808
+ src: mediaItem.url
1809
+ })
1810
+ }, `mastodon-preview__media-item-${index}`))
1811
+ }) : null
1812
+ }),
1813
+ !media?.length && props.customText?.includes(props.url) ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MastodonPostCard, { ...props }) : null,
1814
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MastodonPostActions, {})
1815
+ ]
1816
+ });
1817
+ };
1818
+ //#endregion
1819
+ //#region src/mastodon-preview/previews.tsx
1820
+ const MastodonPreviews = ({ headingLevel, hidePostPreview, hideLinkPreview, ...props }) => {
1821
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1822
+ className: "social-preview mastodon-preview",
1823
+ children: [!hidePostPreview && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
1824
+ className: "social-preview__section mastodon-preview__section",
1825
+ children: [
1826
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SectionHeading, {
1827
+ level: headingLevel,
1828
+ children: (0, _wordpress_i18n.__)("Your post", "social-previews")
1829
+ }),
1830
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1831
+ className: "social-preview__section-desc",
1832
+ children: (0, _wordpress_i18n.__)("This is what your social post will look like on Mastodon:", "social-previews")
1833
+ }),
1834
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MastodonPostPreview, { ...props })
1835
+ ]
1836
+ }), !hideLinkPreview && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
1837
+ className: "social-preview__section mastodon-preview__section",
1838
+ children: [
1839
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SectionHeading, {
1840
+ level: headingLevel,
1841
+ children: (0, _wordpress_i18n.__)("Link preview", "social-previews")
1842
+ }),
1843
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1844
+ className: "social-preview__section-desc",
1845
+ children: (0, _wordpress_i18n.__)("This is what it will look like when someone shares the link to your WordPress post on Mastodon.", "social-previews")
1846
+ }),
1847
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MastodonLinkPreview, {
1848
+ ...props,
1849
+ user: void 0
1850
+ })
1851
+ ]
1852
+ })]
1853
+ });
1854
+ };
1855
+ //#endregion
1856
+ //#region src/nextdoor-preview/constants.ts
1857
+ const FEED_TEXT_MAX_LENGTH$1 = 65e3;
1858
+ //#endregion
1859
+ //#region src/nextdoor-preview/icons/comment-icon.tsx
1860
+ /**
1861
+ * Comment Icon Component
1862
+ *
1863
+ * @return The Comment SVG icon component.
1864
+ */
1865
+ function CommentIcon() {
1866
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
1867
+ width: "20",
1868
+ height: "20",
1869
+ fill: "none",
1870
+ viewBox: "0 0 24 24",
1871
+ "aria-hidden": "true",
1872
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
1873
+ fill: "currentColor",
1874
+ fillRule: "evenodd",
1875
+ d: "M2 10.031C2 5.596 5.574 2 10 2h4c4.427 0 8 3.596 8 8.031 0 4.435-3.573 8.031-8 8.031h-1.52a17.033 17.033 0 0 1-1.377 1.467c-.991.938-2.456 2.079-4.086 2.437a1.403 1.403 0 0 1-1.458-.565 1.55 1.55 0 0 1-.195-1.394c.28-.823.395-1.734.434-2.464.014-.257.018-.485.018-.672A8.017 8.017 0 0 1 2 10.031Zm5.798 6.178a7.02 7.02 0 0 1 .016.418c.005.252.004.606-.019 1.023-.03.573-.103 1.285-.266 2.024.775-.377 1.54-.974 2.202-1.598a15.066 15.066 0 0 0 1.448-1.586l.017-.022.003-.004a1 1 0 0 1 .801-.402h2c3.314 0 6-2.692 6-6.03C20 6.691 17.314 4 14 4h-4c-3.314 0-6 2.692-6 6.031 0 2.336 1.32 4.36 3.258 5.359.308.159.515.474.54.82Z",
1876
+ clipRule: "evenodd"
1877
+ })
1878
+ });
1879
+ }
1880
+ //#endregion
1881
+ //#region src/nextdoor-preview/icons/like-icon.tsx
1882
+ /**
1883
+ * Like Icon component.
1884
+ *
1885
+ * @return Like Icon component.
1886
+ */
1887
+ function LikeIcon() {
1888
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
1889
+ width: "20",
1890
+ height: "20",
1891
+ fill: "none",
1892
+ viewBox: "0 0 24 24",
1893
+ "aria-hidden": "true",
1894
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
1895
+ fill: "currentColor",
1896
+ fillRule: "evenodd",
1897
+ d: "M13.275 8.752a1.5 1.5 0 0 1-2.55 0C9.75 7.18 8.719 5.617 6.565 6.074 5.248 6.352 4 7.433 4 9.644c0 2.153 1.348 4.592 4.259 7.236A28.475 28.475 0 0 0 12 19.74a28.475 28.475 0 0 0 3.741-2.86C18.651 14.236 20 11.797 20 9.643c0-2.21-1.25-3.29-2.564-3.57-2.155-.456-3.187 1.106-4.16 2.68Zm-2.581-3.48C7.634 2.58 2 4.217 2 9.643c0 2.996 1.85 5.934 4.914 8.717 1.478 1.343 3.1 2.585 4.839 3.575a.5.5 0 0 0 .494 0c1.739-.99 3.361-2.232 4.84-3.575C20.148 15.577 22 12.64 22 9.643c0-5.426-5.634-7.062-8.694-4.371A5.287 5.287 0 0 0 12 7.04a5.287 5.287 0 0 0-1.306-1.77Z",
1898
+ clipRule: "evenodd"
1899
+ })
1900
+ });
1901
+ }
1902
+ //#endregion
1903
+ //#region src/nextdoor-preview/icons/share-icon.tsx
1904
+ /**
1905
+ * Share Icon Component
1906
+ *
1907
+ * @return The Share SVG icon component.
1908
+ */
1909
+ function ShareIcon() {
1910
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
1911
+ width: "20",
1912
+ height: "20",
1913
+ fill: "none",
1914
+ viewBox: "0 0 24 24",
1915
+ "aria-hidden": "true",
1916
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
1917
+ fill: "currentColor",
1918
+ fillRule: "evenodd",
1919
+ d: "M11.617 2.076a1 1 0 0 1 1.09.217l9 9a1 1 0 0 1 0 1.414l-9 9A1 1 0 0 1 11 21v-4.436c-2.849.366-5.261 2.271-6.384 4.837a1 1 0 0 1-1.856-.06C2.338 20.182 2 18.86 2 17.5a9.959 9.959 0 0 1 9-9.951V3a1 1 0 0 1 .617-.924ZM13 5.414V8.5a1 1 0 0 1-1 1c-4.448 0-8 3.552-8 8 0 .31.023.625.066.94C5.905 16.067 8.776 14.5 12 14.5a1 1 0 0 1 1 1v3.086L19.586 12 13 5.414Z",
1920
+ clipRule: "evenodd"
1921
+ })
1922
+ });
1923
+ }
1924
+ //#endregion
1925
+ //#region src/nextdoor-preview/footer-actions.tsx
1926
+ /**
1927
+ * Footer Actions Component
1928
+ *
1929
+ * @return The Nextdoor footer actions component.
1930
+ */
1931
+ function FooterActions() {
1932
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1933
+ className: "nextdoor-preview__footer--actions",
1934
+ children: [
1935
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1936
+ className: "nextdoor-preview__footer--actions-item",
1937
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(LikeIcon, {}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: (0, _wordpress_i18n.__)("Like", "social-previews") })]
1938
+ }),
1939
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1940
+ className: "nextdoor-preview__footer--actions-item",
1941
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(CommentIcon, {}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: (0, _wordpress_i18n.__)("Comment", "social-previews") })]
1942
+ }),
1943
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1944
+ className: "nextdoor-preview__footer--actions-item",
1945
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ShareIcon, {}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: (0, _wordpress_i18n.__)("Share", "social-previews") })]
1946
+ })
1947
+ ]
1948
+ });
1949
+ }
1950
+ //#endregion
1951
+ //#region src/nextdoor-preview/icons/chevron-icon.tsx
1952
+ /**
1953
+ * Chevron Icon Component
1954
+ *
1955
+ * @return The Chevron SVG icon component.
1956
+ */
1957
+ function ChevronIcon() {
1958
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
1959
+ width: "20",
1960
+ height: "20",
1961
+ viewBox: "0 0 20 20",
1962
+ "aria-hidden": "true",
1963
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
1964
+ fill: "#dfe1e4",
1965
+ fillRule: "evenodd",
1966
+ d: "M7.127 13.876a.732.732 0 1 0 1.035 1.035l4.75-4.749a.732.732 0 0 0 0-1.035L8.123 4.34A.732.732 0 0 0 7.09 5.375l4.27 4.27-4.232 4.23Z"
1967
+ })
1968
+ });
1969
+ }
1970
+ //#endregion
1971
+ //#region src/nextdoor-preview/icons/default-image.tsx
1972
+ /**
1973
+ * Default Image Icon Component
1974
+ *
1975
+ * @return The Default Image SVG icon component.
1976
+ */
1977
+ function DefaultImage() {
1978
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1979
+ className: "nextdoor-preview__default-image",
1980
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
1981
+ width: "24",
1982
+ height: "24",
1983
+ fill: "none",
1984
+ viewBox: "0 0 24 24",
1985
+ "aria-hidden": "true",
1986
+ color: "#055c00",
1987
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
1988
+ fill: "currentColor",
1989
+ d: "M13.207 5.207c1.51-1.51 4.076-1.51 5.586 0 1.51 1.51 1.51 4.076 0 5.586l-2.1 2.1c-1.51 1.51-4.077 1.51-5.586 0a1 1 0 1 0-1.414 1.414c2.29 2.29 6.123 2.29 8.414 0l2.1-2.1c2.29-2.29 2.29-6.124 0-8.414s-6.124-2.29-8.414 0l-.7.7a1 1 0 0 0 1.414 1.414l.7-.7Z"
1990
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
1991
+ fill: "currentColor",
1992
+ d: "M7.307 11.107c1.51-1.51 4.076-1.51 5.586 0a1 1 0 0 0 1.414-1.414c-2.29-2.29-6.124-2.29-8.414 0l-2.1 2.1c-2.29 2.29-2.29 6.123 0 8.414 2.29 2.29 6.124 2.29 8.414 0l.7-.7a1 1 0 0 0-1.414-1.414l-.7.7c-1.51 1.51-4.076 1.51-5.586 0-1.51-1.51-1.51-4.076 0-5.586l2.1-2.1Z"
1993
+ })]
1994
+ })
1995
+ });
1996
+ }
1997
+ //#endregion
1998
+ //#region src/nextdoor-preview/icons/globe-icon.tsx
1999
+ /**
2000
+ * Globe Icon Component
2001
+ *
2002
+ * @return The Globe SVG icon component.
2003
+ */
2004
+ function GlobeIcon() {
2005
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
2006
+ width: "14",
2007
+ height: "14",
2008
+ fill: "none",
2009
+ viewBox: "0 0 24 24",
2010
+ "aria-hidden": "true",
2011
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
2012
+ fill: "currentColor",
2013
+ fillRule: "evenodd",
2014
+ d: "M2 12C2 6.477 6.477 2 12 2s10 4.477 10 10-4.477 10-10 10S2 17.523 2 12Zm9.495-7.643c.286-.335.46-.357.505-.357.045 0 .219.022.505.357.282.33.581.868.852 1.619.464 1.283.79 3.034.872 5.024H9.771c.082-1.99.408-3.741.871-5.024.272-.751.571-1.289.854-1.62ZM7.77 11c.084-2.181.439-4.171.992-5.704.093-.255.192-.502.298-.738A8.009 8.009 0 0 0 4.062 11h3.707Zm-3.707 2h3.707c.084 2.181.439 4.171.992 5.704.093.255.192.502.298.738A8.009 8.009 0 0 1 4.062 13Zm15.876-2a8.009 8.009 0 0 0-4.997-6.442c.106.236.205.483.298.738.553 1.533.908 3.523.992 5.704h3.707Zm-3.707 2h3.707a8.009 8.009 0 0 1-4.997 6.442c.106-.236.205-.483.298-.738.553-1.533.908-3.523.992-5.704Zm-2.002 0c-.082 1.99-.408 3.741-.871 5.024-.272.751-.571 1.289-.854 1.62-.285.334-.46.356-.504.356-.045 0-.219-.022-.505-.357-.282-.33-.581-.868-.852-1.619-.464-1.283-.79-3.034-.872-5.024h4.458Z",
2015
+ clipRule: "evenodd"
2016
+ })
2017
+ });
2018
+ }
2019
+ //#endregion
2020
+ //#region src/nextdoor-preview/post-preview.tsx
2021
+ /**
2022
+ * Nextdoor Post Preview Component.
2023
+ *
2024
+ * @param {NextdoorPreviewProps} props - The preview properties.
2025
+ * @return The Nextdoor post preview component.
2026
+ */
2027
+ function NextdoorPostPreview({ image, imageFocalPoint, name, profileImage, description, neighborhood, media, title, url }) {
2028
+ const hasMedia = !!media?.length;
2029
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2030
+ className: "nextdoor-preview__wrapper",
2031
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("section", {
2032
+ className: `nextdoor-preview__container ${hasMedia ? "has-media" : ""}`,
2033
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2034
+ className: "nextdoor-preview__content",
2035
+ children: [
2036
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2037
+ className: "nextdoor-preview__header",
2038
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2039
+ className: "nextdoor-preview__header--avatar",
2040
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AvatarWithFallback, { src: profileImage })
2041
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2042
+ className: "nextdoor-preview__header--details",
2043
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2044
+ className: "nextdoor-preview__header--name",
2045
+ children: name || (0, _wordpress_i18n.__)("Account Name", "social-previews")
2046
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2047
+ className: "nextdoor-preview__header--meta",
2048
+ children: [
2049
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: neighborhood || (0, _wordpress_i18n.__)("Neighborhood", "social-previews") }),
2050
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "•" }),
2051
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: formatNextdoorDate(Date.now()) }),
2052
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "•" }),
2053
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(GlobeIcon, {})
2054
+ ]
2055
+ })]
2056
+ })]
2057
+ }),
2058
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2059
+ className: "nextdoor-preview__body",
2060
+ children: [
2061
+ description ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2062
+ className: "nextdoor-preview__caption",
2063
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ExpandableText, {
2064
+ text: description,
2065
+ children: (visibleText) => preparePreviewText(visibleText, {
2066
+ platform: "nextdoor",
2067
+ maxChars: FEED_TEXT_MAX_LENGTH$1
2068
+ })
2069
+ }) })
2070
+ }) : null,
2071
+ hasMedia ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2072
+ className: "nextdoor-preview__media",
2073
+ children: media.map((mediaItem, index) => {
2074
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2075
+ className: "nextdoor-preview__media-item",
2076
+ children: mediaItem?.type?.startsWith("video/") ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("video", {
2077
+ controls: true,
2078
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("source", {
2079
+ src: mediaItem.url,
2080
+ type: mediaItem.type
2081
+ })
2082
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
2083
+ alt: mediaItem.alt || "",
2084
+ src: mediaItem.url
2085
+ })
2086
+ }, `nextdoor-preview__media-item-${index}`);
2087
+ })
2088
+ }) : null,
2089
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("article", {
2090
+ className: (0, clsx.default)("nextdoor-preview__card", { "small-preview": !image || hasMedia }),
2091
+ children: [
2092
+ image ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MediaImage, {
2093
+ className: "nextdoor-preview__image",
2094
+ src: image,
2095
+ alt: "",
2096
+ focalPoint: imageFocalPoint
2097
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DefaultImage, {}),
2098
+ url ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2099
+ className: "nextdoor-preview__description",
2100
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
2101
+ className: "nextdoor-preview__description--title",
2102
+ children: title || getTitleFromDescription(description)
2103
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2104
+ className: "nextdoor-preview__description--url",
2105
+ children: baseDomain(url)
2106
+ })]
2107
+ }) : null,
2108
+ hasMedia ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2109
+ className: "nextdoor-preview__card--chevron-wrapper",
2110
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ChevronIcon, {})
2111
+ }) : null
2112
+ ]
2113
+ })
2114
+ ]
2115
+ }),
2116
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2117
+ className: "nextdoor-preview__footer",
2118
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FooterActions, {})
2119
+ })
2120
+ ]
2121
+ })
2122
+ })
2123
+ });
2124
+ }
2125
+ //#endregion
2126
+ //#region src/nextdoor-preview/link-preview.tsx
2127
+ /**
2128
+ * Nextdoor Link Preview Component
2129
+ *
2130
+ * @param {NextdoorLinkPreviewProps} props - The props for the Nextdoor link preview.
2131
+ *
2132
+ * @return The Nextdoor link preview component.
2133
+ */
2134
+ function NextdoorLinkPreview(props) {
2135
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(NextdoorPostPreview, {
2136
+ name: "",
2137
+ profileImage: "",
2138
+ ...props,
2139
+ description: "",
2140
+ media: void 0,
2141
+ title: props.title || getTitleFromDescription(props.description)
2142
+ });
2143
+ }
2144
+ //#endregion
2145
+ //#region src/nextdoor-preview/previews.tsx
2146
+ const NextdoorPreviews = ({ headingLevel, hideLinkPreview, hidePostPreview, ...props }) => {
2147
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2148
+ className: "social-preview nextdoor-preview",
2149
+ children: [!hidePostPreview && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
2150
+ className: "social-preview__section nextdoor-preview__section",
2151
+ children: [
2152
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SectionHeading, {
2153
+ level: headingLevel,
2154
+ children: (0, _wordpress_i18n.__)("Your post", "social-previews")
2155
+ }),
2156
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2157
+ className: "social-preview__section-desc",
2158
+ children: (0, _wordpress_i18n.__)("This is what your social post will look like on Nextdoor:", "social-previews")
2159
+ }),
2160
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(NextdoorPostPreview, { ...props })
2161
+ ]
2162
+ }), !hideLinkPreview && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
2163
+ className: "social-preview__section nextdoor-preview__section",
2164
+ children: [
2165
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SectionHeading, {
2166
+ level: headingLevel,
2167
+ children: (0, _wordpress_i18n.__)("Link preview", "social-previews")
2168
+ }),
2169
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2170
+ className: "social-preview__section-desc",
2171
+ children: (0, _wordpress_i18n.__)("This is what it will look like when someone shares the link to your WordPress post on Nextdoor.", "social-previews")
2172
+ }),
2173
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(NextdoorLinkPreview, {
2174
+ ...props,
2175
+ name: "",
2176
+ profileImage: ""
2177
+ })
2178
+ ]
2179
+ })]
2180
+ });
2181
+ };
2182
+ //#endregion
2183
+ //#region src/bluesky-preview/post/actions/index.tsx
2184
+ const BlueskyPostActions = () => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2185
+ className: "bluesky-preview__post-actions",
2186
+ children: [
2187
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
2188
+ fill: "none",
2189
+ width: "18",
2190
+ viewBox: "0 0 24 24",
2191
+ height: "18",
2192
+ style: { color: "rgb(111, 134, 159)" },
2193
+ "aria-hidden": "true",
2194
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
2195
+ fill: "hsl(211, 20%, 53%)",
2196
+ fillRule: "evenodd",
2197
+ clipRule: "evenodd",
2198
+ d: "M2.002 6a3 3 0 0 1 3-3h14a3 3 0 0 1 3 3v10a3 3 0 0 1-3 3H12.28l-4.762 2.858A1 1 0 0 1 6.002 21v-2h-1a3 3 0 0 1-3-3V6Zm3-1a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h2a1 1 0 0 1 1 1v1.234l3.486-2.092a1 1 0 0 1 .514-.142h7a1 1 0 0 0 1-1V6a1 1 0 0 0-1-1h-14Z"
2199
+ })
2200
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: 0 })] }),
2201
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
2202
+ fill: "none",
2203
+ width: "18",
2204
+ viewBox: "0 0 24 24",
2205
+ height: "18",
2206
+ style: { color: "rgb(111, 134, 159)" },
2207
+ "aria-hidden": "true",
2208
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
2209
+ fill: "hsl(211, 20%, 53%)",
2210
+ fillRule: "evenodd",
2211
+ clipRule: "evenodd",
2212
+ d: "M17.957 2.293a1 1 0 1 0-1.414 1.414L17.836 5H6a3 3 0 0 0-3 3v3a1 1 0 1 0 2 0V8a1 1 0 0 1 1-1h11.836l-1.293 1.293a1 1 0 0 0 1.414 1.414l2.47-2.47a1.75 1.75 0 0 0 0-2.474l-2.47-2.47ZM20 12a1 1 0 0 1 1 1v3a3 3 0 0 1-3 3H6.164l1.293 1.293a1 1 0 1 1-1.414 1.414l-2.47-2.47a1.75 1.75 0 0 1 0-2.474l2.47-2.47a1 1 0 0 1 1.414 1.414L6.164 17H18a1 1 0 0 0 1-1v-3a1 1 0 0 1 1-1Z"
2213
+ })
2214
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: 0 })] }),
2215
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
2216
+ fill: "none",
2217
+ width: "18",
2218
+ viewBox: "0 0 24 24",
2219
+ height: "18",
2220
+ style: { color: "rgb(111, 134, 159)" },
2221
+ "aria-hidden": "true",
2222
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
2223
+ fill: "hsl(211, 20%, 53%)",
2224
+ fillRule: "evenodd",
2225
+ clipRule: "evenodd",
2226
+ d: "M16.734 5.091c-1.238-.276-2.708.047-4.022 1.38a1 1 0 0 1-1.424 0C9.974 5.137 8.504 4.814 7.266 5.09c-1.263.282-2.379 1.206-2.92 2.556C3.33 10.18 4.252 14.84 12 19.348c7.747-4.508 8.67-9.168 7.654-11.7-.541-1.351-1.657-2.275-2.92-2.557Zm4.777 1.812c1.604 4-.494 9.69-9.022 14.47a1 1 0 0 1-.978 0C2.983 16.592.885 10.902 2.49 6.902c.779-1.942 2.414-3.334 4.342-3.764 1.697-.378 3.552.003 5.169 1.286 1.617-1.283 3.472-1.664 5.17-1.286 1.927.43 3.562 1.822 4.34 3.764Z"
2227
+ })
2228
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: 0 })] }),
2229
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
2230
+ fill: "none",
2231
+ viewBox: "0 0 24 24",
2232
+ width: "20",
2233
+ height: "20",
2234
+ "aria-hidden": "true",
2235
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
2236
+ fill: "hsl(211, 20%, 53%)",
2237
+ fillRule: "evenodd",
2238
+ clipRule: "evenodd",
2239
+ d: "M2 12a2 2 0 1 1 4 0 2 2 0 0 1-4 0Zm16 0a2 2 0 1 1 4 0 2 2 0 0 1-4 0Zm-6-2a2 2 0 1 0 0 4 2 2 0 0 0 0-4Z"
2240
+ })
2241
+ }) })
2242
+ ]
2243
+ });
2244
+ //#endregion
2245
+ //#region src/bluesky-preview/helpers.ts
2246
+ const TITLE_LENGTH$1 = 200;
2247
+ const BODY_LENGTH = 300;
2248
+ const URL_LENGTH = 40;
2249
+ const blueskyTitle = (text) => firstValid(shortEnough(TITLE_LENGTH$1), hardTruncation(TITLE_LENGTH$1))(stripHtmlTags(text)) || "";
2250
+ const blueskyBody = (text, options = {}) => {
2251
+ const { offset = 0, reserveUrlSpace = true, hyperlinks } = options;
2252
+ return preparePreviewText(text, {
2253
+ platform: "bluesky",
2254
+ maxChars: BODY_LENGTH - (reserveUrlSpace ? URL_LENGTH : 0) - offset,
2255
+ hyperlinks
2256
+ });
2257
+ };
2258
+ const blueskyUrl = (text) => firstValid(shortEnough(URL_LENGTH), hardTruncation(URL_LENGTH))(stripHtmlTags(text)) || "";
2259
+ //#endregion
2260
+ //#region src/bluesky-preview/post/body/index.tsx
2261
+ const BlueskyPostBody = ({ customText, url, children, appendUrl, hyperlinks }) => {
2262
+ const showUrl = appendUrl && !!url && !customText?.includes(url);
2263
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2264
+ className: "bluesky-preview__body",
2265
+ children: [customText ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: blueskyBody(customText, {
2266
+ reserveUrlSpace: showUrl,
2267
+ hyperlinks
2268
+ }) }), showUrl ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("br", {}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
2269
+ href: url,
2270
+ target: "_blank",
2271
+ rel: "noreferrer noopener",
2272
+ children: blueskyUrl(url.replace(/^https?:\/\//, ""))
2273
+ })] }) : null] }) : null, children]
2274
+ });
2275
+ };
2276
+ //#endregion
2277
+ //#region src/bluesky-preview/post/card/index.tsx
2278
+ const BlueskyPostCard = ({ title, description, url, image, imageFocalPoint }) => {
2279
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2280
+ className: "bluesky-preview__card",
2281
+ children: [image ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2282
+ className: "bluesky-preview__card-image",
2283
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MediaImage, {
2284
+ src: image,
2285
+ alt: "",
2286
+ focalPoint: imageFocalPoint
2287
+ })
2288
+ }) : null, /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2289
+ className: "bluesky-preview__card-text",
2290
+ children: [
2291
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2292
+ className: "bluesky-preview__card-site",
2293
+ children: baseDomain(url)
2294
+ }),
2295
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2296
+ className: "bluesky-preview__card-title",
2297
+ children: blueskyTitle(title) || getTitleFromDescription(description)
2298
+ }),
2299
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2300
+ className: "bluesky-preview__card-description",
2301
+ children: stripHtmlTags(description)
2302
+ })
2303
+ ]
2304
+ })]
2305
+ });
2306
+ };
2307
+ //#endregion
2308
+ //#region src/bluesky-preview/post/header/index.tsx
2309
+ const BlueskyPostHeader = ({ user }) => {
2310
+ const { displayName, address } = user || {};
2311
+ let handle = address || "username.bsky.social";
2312
+ if (!handle.startsWith("@")) handle = "@" + handle;
2313
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2314
+ className: "bluesky-preview__post-header",
2315
+ children: [
2316
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2317
+ className: "bluesky-preview__post-header-user",
2318
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2319
+ className: "bluesky-preview__post-header--displayname",
2320
+ children: displayName || (0, _wordpress_i18n.__)("Account name", "social-previews")
2321
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2322
+ className: "bluesky-preview__post-header--username",
2323
+ children: handle
2324
+ })]
2325
+ }),
2326
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2327
+ className: "bluesky-preview__post-header--separator",
2328
+ children: "·"
2329
+ }),
2330
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2331
+ className: "bluesky-preview__post-header--date",
2332
+ children: (0, _wordpress_i18n._x)("1h", "refers to the time since the post was published, e.g. \"1h\"", "social-previews")
2333
+ })
2334
+ ]
2335
+ });
2336
+ };
2337
+ //#endregion
2338
+ //#region src/bluesky-preview/post/sidebar/index.tsx
2339
+ const BlueskyPostSidebar = ({ user }) => {
2340
+ const { avatarUrl } = user || {};
2341
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2342
+ className: "bluesky-preview__post-sidebar",
2343
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2344
+ className: "bluesky-preview__post-sidebar-user",
2345
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AvatarWithFallback, {
2346
+ className: "bluesky-preview__post-avatar",
2347
+ src: avatarUrl
2348
+ })
2349
+ })
2350
+ });
2351
+ };
2352
+ //#endregion
2353
+ //#region src/bluesky-preview/post-preview.tsx
2354
+ const BlueskyPostPreview = (props) => {
2355
+ const { user, media } = props;
2356
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2357
+ className: "bluesky-preview__post",
2358
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(BlueskyPostSidebar, { user }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [
2359
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BlueskyPostHeader, { user }),
2360
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BlueskyPostBody, {
2361
+ ...props,
2362
+ children: media?.length ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2363
+ className: (0, clsx.default)("bluesky-preview__media", { "as-grid": media.length > 1 }),
2364
+ children: media.map((mediaItem, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2365
+ className: "bluesky-preview__media-item",
2366
+ children: mediaItem.type.startsWith("video/") ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("video", {
2367
+ controls: true,
2368
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("source", {
2369
+ src: mediaItem.url,
2370
+ type: mediaItem.type
2371
+ })
2372
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
2373
+ alt: mediaItem.alt || "",
2374
+ src: mediaItem.url
2375
+ })
2376
+ }, `bluesky-preview__media-item-${index}`))
2377
+ }) : null
2378
+ }),
2379
+ !media?.length ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BlueskyPostCard, { ...props }) : null,
2380
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BlueskyPostActions, {})
2381
+ ] })]
2382
+ });
2383
+ };
2384
+ //#endregion
2385
+ //#region src/bluesky-preview/link-preview.tsx
2386
+ const BlueskyLinkPreview = (props) => {
2387
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BlueskyPostPreview, {
2388
+ ...props,
2389
+ user: void 0,
2390
+ media: void 0,
2391
+ customText: ""
2392
+ });
2393
+ };
2394
+ //#endregion
2395
+ //#region src/bluesky-preview/previews.tsx
2396
+ const BlueskyPreviews = ({ headingLevel, hidePostPreview, hideLinkPreview, ...props }) => {
2397
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2398
+ className: "social-preview bluesky-preview",
2399
+ children: [!hidePostPreview && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
2400
+ className: "social-preview__section bluesky-preview__section",
2401
+ children: [
2402
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SectionHeading, {
2403
+ level: headingLevel,
2404
+ children: (0, _wordpress_i18n.__)("Your post", "social-previews")
2405
+ }),
2406
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2407
+ className: "social-preview__section-desc",
2408
+ children: (0, _wordpress_i18n.__)("This is what your social post will look like on Bluesky:", "social-previews")
2409
+ }),
2410
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BlueskyPostPreview, { ...props })
2411
+ ]
2412
+ }), !hideLinkPreview && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
2413
+ className: "social-preview__section bluesky-preview__section",
2414
+ children: [
2415
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SectionHeading, {
2416
+ level: headingLevel,
2417
+ children: (0, _wordpress_i18n.__)("Link preview", "social-previews")
2418
+ }),
2419
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2420
+ className: "social-preview__section-desc",
2421
+ children: (0, _wordpress_i18n.__)("This is what it will look like when someone shares the link to your WordPress post on Bluesky.", "social-previews")
2422
+ }),
2423
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BlueskyLinkPreview, { ...props })
2424
+ ]
2425
+ })]
2426
+ });
2427
+ };
2428
+ //#endregion
2429
+ //#region src/threads-preview/helpers.ts
2430
+ const TITLE_LENGTH = 120;
2431
+ const threadsTitle = (text) => firstValid(shortEnough(TITLE_LENGTH), hardTruncation(TITLE_LENGTH))(stripHtmlTags(text)) || "";
2432
+ //#endregion
2433
+ //#region src/threads-preview/card.tsx
2434
+ const Card = ({ image, imageFocalPoint, title, url }) => {
2435
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2436
+ className: "threads-preview__card",
2437
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2438
+ className: (0, clsx.default)({ "threads-preview__card-has-image": !!image }),
2439
+ children: [image && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MediaImage, {
2440
+ className: "threads-preview__card-image",
2441
+ src: image,
2442
+ alt: "",
2443
+ focalPoint: imageFocalPoint
2444
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2445
+ className: "threads-preview__card-body",
2446
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2447
+ className: "threads-preview__card-url",
2448
+ children: baseDomain(url || "")
2449
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2450
+ className: "threads-preview__card-title",
2451
+ children: threadsTitle(title)
2452
+ })]
2453
+ })]
2454
+ })
2455
+ });
2456
+ };
2457
+ //#endregion
2458
+ //#region src/threads-preview/footer.tsx
2459
+ const Footer = () => {
2460
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2461
+ className: "threads-preview__footer",
2462
+ children: [
2463
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2464
+ className: "threads-preview__icon--like",
2465
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
2466
+ role: "img",
2467
+ viewBox: "0 0 18 18",
2468
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
2469
+ d: "M1.34375 7.53125L1.34375 7.54043C1.34374 8.04211 1.34372 8.76295 1.6611 9.65585C1.9795 10.5516 2.60026 11.5779 3.77681 12.7544C5.59273 14.5704 7.58105 16.0215 8.33387 16.5497C8.73525 16.8313 9.26573 16.8313 9.66705 16.5496C10.4197 16.0213 12.4074 14.5703 14.2232 12.7544C15.3997 11.5779 16.0205 10.5516 16.3389 9.65585C16.6563 8.76296 16.6563 8.04211 16.6562 7.54043V7.53125C16.6562 5.23466 15.0849 3.25 12.6562 3.25C11.5214 3.25 10.6433 3.78244 9.99228 4.45476C9.59009 4.87012 9.26356 5.3491 9 5.81533C8.73645 5.3491 8.40991 4.87012 8.00772 4.45476C7.35672 3.78244 6.47861 3.25 5.34375 3.25C2.9151 3.25 1.34375 5.23466 1.34375 7.53125Z",
2470
+ strokeWidth: "1.25"
2471
+ })
2472
+ })
2473
+ }),
2474
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2475
+ className: "threads-preview__icon--reply",
2476
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
2477
+ role: "img",
2478
+ viewBox: "0 0 18 18",
2479
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
2480
+ d: "M15.376 13.2177L16.2861 16.7955L12.7106 15.8848C12.6781 15.8848 12.6131 15.8848 12.5806 15.8848C11.3779 16.5678 9.94767 16.8931 8.41995 16.7955C4.94194 16.5353 2.08152 13.7381 1.72397 10.2578C1.2689 5.63919 5.13697 1.76863 9.75264 2.22399C13.2307 2.58177 16.0261 5.41151 16.2861 8.92429C16.4161 10.453 16.0586 11.8841 15.376 13.0876C15.376 13.1526 15.376 13.1852 15.376 13.2177Z",
2481
+ strokeLinejoin: "round",
2482
+ strokeWidth: "1.25"
2483
+ })
2484
+ })
2485
+ }),
2486
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2487
+ className: "threads-preview__icon--repost",
2488
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
2489
+ role: "img",
2490
+ viewBox: "0 0 18 18",
2491
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M6.41256 1.23531C6.6349 0.971277 7.02918 0.937481 7.29321 1.15982L9.96509 3.40982C10.1022 3.52528 10.1831 3.69404 10.1873 3.87324C10.1915 4.05243 10.1186 4.2248 9.98706 4.34656L7.31518 6.81971C7.06186 7.05419 6.66643 7.03892 6.43196 6.7856C6.19748 6.53228 6.21275 6.13685 6.46607 5.90237L7.9672 4.51289H5.20312C3.68434 4.51289 2.45312 5.74411 2.45312 7.26289V9.51289V11.7629C2.45312 13.2817 3.68434 14.5129 5.20312 14.5129C5.5483 14.5129 5.82812 14.7927 5.82812 15.1379C5.82812 15.4831 5.5483 15.7629 5.20312 15.7629C2.99399 15.7629 1.20312 13.972 1.20312 11.7629V9.51289V7.26289C1.20312 5.05375 2.99399 3.26289 5.20312 3.26289H7.85002L6.48804 2.11596C6.22401 1.89362 6.19021 1.49934 6.41256 1.23531Z" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M11.5874 17.7904C11.3651 18.0545 10.9708 18.0883 10.7068 17.8659L8.03491 15.6159C7.89781 15.5005 7.81687 15.3317 7.81267 15.1525C7.80847 14.9733 7.8814 14.801 8.01294 14.6792L10.6848 12.206C10.9381 11.9716 11.3336 11.9868 11.568 12.2402C11.8025 12.4935 11.7872 12.8889 11.5339 13.1234L10.0328 14.5129H12.7969C14.3157 14.5129 15.5469 13.2816 15.5469 11.7629V9.51286V7.26286C15.5469 5.74408 14.3157 4.51286 12.7969 4.51286C12.4517 4.51286 12.1719 4.23304 12.1719 3.88786C12.1719 3.54269 12.4517 3.26286 12.7969 3.26286C15.006 3.26286 16.7969 5.05373 16.7969 7.26286V9.51286V11.7629C16.7969 13.972 15.006 15.7629 12.7969 15.7629H10.15L11.512 16.9098C11.776 17.1321 11.8098 17.5264 11.5874 17.7904Z" })]
2492
+ })
2493
+ }),
2494
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2495
+ className: "threads-preview__icon--share",
2496
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
2497
+ role: "img",
2498
+ viewBox: "0 0 18 18",
2499
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
2500
+ d: "M15.6097 4.09082L6.65039 9.11104",
2501
+ strokeLinejoin: "round",
2502
+ strokeWidth: "1.25"
2503
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
2504
+ d: "M7.79128 14.439C8.00463 15.3275 8.11131 15.7718 8.33426 15.932C8.52764 16.071 8.77617 16.1081 9.00173 16.0318C9.26179 15.9438 9.49373 15.5501 9.95761 14.7628L15.5444 5.2809C15.8883 4.69727 16.0603 4.40546 16.0365 4.16566C16.0159 3.95653 15.9071 3.76612 15.7374 3.64215C15.5428 3.5 15.2041 3.5 14.5267 3.5H3.71404C2.81451 3.5 2.36474 3.5 2.15744 3.67754C1.97758 3.83158 1.88253 4.06254 1.90186 4.29856C1.92415 4.57059 2.24363 4.88716 2.88259 5.52032L6.11593 8.7243C6.26394 8.87097 6.33795 8.94431 6.39784 9.02755C6.451 9.10144 6.4958 9.18101 6.53142 9.26479C6.57153 9.35916 6.59586 9.46047 6.64451 9.66309L7.79128 14.439Z",
2505
+ strokeLinejoin: "round",
2506
+ strokeWidth: "1.25"
2507
+ })]
2508
+ })
2509
+ })
2510
+ ]
2511
+ });
2512
+ };
2513
+ //#endregion
2514
+ //#region src/threads-preview/header.tsx
2515
+ const Header = ({ name, date }) => {
2516
+ const postDate = date || /* @__PURE__ */ new Date();
2517
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2518
+ className: "threads-preview__header",
2519
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2520
+ className: "threads-preview__name",
2521
+ children: name || (0, _wordpress_i18n.__)("Account Name", "social-previews")
2522
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("time", {
2523
+ className: "threads-preview__date",
2524
+ dateTime: postDate.toISOString(),
2525
+ children: formatThreadsDate(postDate)
2526
+ })]
2527
+ });
2528
+ };
2529
+ //#endregion
2530
+ //#region src/threads-preview/media.tsx
2531
+ const Media = ({ media }) => {
2532
+ const filteredMedia = media.filter((mediaItem) => mediaItem.type.startsWith("image/") || mediaItem.type.startsWith("video/")).filter((mediaItem, idx, array) => {
2533
+ if (0 === idx) return true;
2534
+ if (array[0].type.startsWith("video/") || "image/gif" === array[0].type) return false;
2535
+ if (mediaItem.type.startsWith("video/") || "image/gif" === mediaItem.type) return false;
2536
+ return true;
2537
+ }).slice(0, 4);
2538
+ if (0 === filteredMedia.length) return null;
2539
+ const isVideo = filteredMedia[0].type.startsWith("video/");
2540
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2541
+ className: (0, clsx.default)(["threads-preview__media", "threads-preview__media-children-" + filteredMedia.length]),
2542
+ children: filteredMedia.map((mediaItem, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react.Fragment, { children: isVideo ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("video", {
2543
+ controls: true,
2544
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("source", {
2545
+ src: mediaItem.url,
2546
+ type: mediaItem.type
2547
+ })
2548
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
2549
+ alt: mediaItem.alt || "",
2550
+ src: mediaItem.url
2551
+ }) }, `threads-preview__media-item-${index}`))
2552
+ });
2553
+ };
2554
+ //#endregion
2555
+ //#region src/threads-preview/sidebar.tsx
2556
+ const Sidebar = ({ profileImage, showThreadConnector }) => {
2557
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2558
+ className: "threads-preview__sidebar",
2559
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2560
+ className: "threads-preview__profile-image",
2561
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AvatarWithFallback, {
2562
+ alt: (0, _wordpress_i18n.__)("Threads profile image", "social-previews"),
2563
+ src: profileImage
2564
+ })
2565
+ }), showThreadConnector && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "threads-preview__connector" })]
2566
+ });
2567
+ };
2568
+ //#endregion
2569
+ //#region src/threads-preview/post-preview.tsx
2570
+ const ThreadsPostPreview = ({ caption, date, image, imageFocalPoint, media, name, profileImage, showThreadConnector, title, url }) => {
2571
+ const hasMedia = !!media?.length;
2572
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2573
+ className: "threads-preview__wrapper",
2574
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2575
+ className: "threads-preview__container",
2576
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Sidebar, {
2577
+ profileImage,
2578
+ showThreadConnector
2579
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2580
+ className: "threads-preview__main",
2581
+ children: [
2582
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Header, {
2583
+ name,
2584
+ date
2585
+ }),
2586
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2587
+ className: "threads-preview__content",
2588
+ children: [
2589
+ caption ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2590
+ className: "threads-preview__text",
2591
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ExpandableText, {
2592
+ text: caption,
2593
+ children: (visibleText) => preparePreviewText(visibleText, {
2594
+ platform: "threads",
2595
+ maxChars: 500
2596
+ })
2597
+ })
2598
+ }) : null,
2599
+ hasMedia ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Media, { media }) : null,
2600
+ url && image && !hasMedia ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Card, {
2601
+ image,
2602
+ imageFocalPoint,
2603
+ title: title || "",
2604
+ url
2605
+ }) : null
2606
+ ]
2607
+ }),
2608
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Footer, {})
2609
+ ]
2610
+ })]
2611
+ })
2612
+ });
2613
+ };
2614
+ //#endregion
2615
+ //#region src/threads-preview/link-preview.tsx
2616
+ const ThreadsLinkPreview = (props) => {
2617
+ if (!props.image) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2618
+ className: "social-preview__section-desc",
2619
+ children: (0, _wordpress_i18n.__)("Threads link preview requires an image to be set for the post. Please add an image to see the preview.", "social-previews")
2620
+ });
2621
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ThreadsPostPreview, {
2622
+ ...props,
2623
+ caption: "",
2624
+ media: void 0
2625
+ });
2626
+ };
2627
+ //#endregion
2628
+ //#region src/threads-preview/previews.tsx
2629
+ const ThreadsPreviews = ({ headingLevel, hideLinkPreview, hidePostPreview, posts }) => {
2630
+ if (!posts?.length) return null;
2631
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2632
+ className: "social-preview threads-preview",
2633
+ children: [!hidePostPreview && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
2634
+ className: "social-preview__section threads-preview__section",
2635
+ children: [
2636
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SectionHeading, {
2637
+ level: headingLevel,
2638
+ children: (0, _wordpress_i18n.__)("Your post", "social-previews")
2639
+ }),
2640
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2641
+ className: "social-preview__section-desc",
2642
+ children: (0, _wordpress_i18n.__)("This is what your social post will look like on Threads:", "social-previews")
2643
+ }),
2644
+ posts.map((post, index) => {
2645
+ const isLast = index + 1 === posts.length;
2646
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ThreadsPostPreview, {
2647
+ ...post,
2648
+ showThreadConnector: !isLast
2649
+ }, `threads-preview__post-${index}`);
2650
+ })
2651
+ ]
2652
+ }), !hideLinkPreview ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
2653
+ className: "social-preview__section threads-preview__section",
2654
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SectionHeading, {
2655
+ level: headingLevel,
2656
+ children: (0, _wordpress_i18n.__)("Link preview", "social-previews")
2657
+ }), posts[0].image ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2658
+ className: "social-preview__section-desc",
2659
+ children: (0, _wordpress_i18n.__)("This is what it will look like when someone shares the link to your WordPress post on Threads.", "social-previews")
2660
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ThreadsLinkPreview, {
2661
+ ...posts[0],
2662
+ name: "",
2663
+ profileImage: ""
2664
+ })] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2665
+ className: "social-preview__section-desc",
2666
+ children: (0, _wordpress_i18n.__)("Threads link preview requires an image to be set for the post. Please add an image to see the preview.", "social-previews")
2667
+ })]
2668
+ }) : null]
2669
+ });
2670
+ };
2671
+ //#endregion
2672
+ //#region src/instagram-preview/constants.tsx
2673
+ const FEED_TEXT_MAX_LENGTH = 2200;
2674
+ //#endregion
2675
+ //#region src/instagram-preview/icons/bookmark.tsx
2676
+ const Bookmark = () => {
2677
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
2678
+ color: "rgb(38, 38, 38)",
2679
+ fill: "rgb(38, 38, 38)",
2680
+ height: "24",
2681
+ role: "img",
2682
+ viewBox: "0 0 24 24",
2683
+ width: "24",
2684
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("polygon", {
2685
+ fill: "none",
2686
+ points: "20 21 12 13.44 4 21 4 3 20 3 20 21",
2687
+ stroke: "currentColor",
2688
+ strokeLinecap: "round",
2689
+ strokeLinejoin: "round",
2690
+ strokeWidth: "2"
2691
+ })
2692
+ });
2693
+ };
2694
+ //#endregion
2695
+ //#region src/instagram-preview/icons/comment.tsx
2696
+ const Comment = () => {
2697
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
2698
+ color: "rgb(38, 38, 38)",
2699
+ fill: "rgb(38, 38, 38)",
2700
+ height: "24",
2701
+ role: "img",
2702
+ viewBox: "0 0 24 24",
2703
+ width: "24",
2704
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
2705
+ d: "M20.656 17.008a9.993 9.993 0 1 0-3.59 3.615L22 22Z",
2706
+ fill: "none",
2707
+ stroke: "currentColor",
2708
+ strokeLinejoin: "round",
2709
+ strokeWidth: "2"
2710
+ })
2711
+ });
2712
+ };
2713
+ //#endregion
2714
+ //#region src/instagram-preview/icons/heart.tsx
2715
+ const Heart = () => {
2716
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
2717
+ color: "rgb(38, 38, 38)",
2718
+ fill: "rgb(38, 38, 38)",
2719
+ height: "24",
2720
+ role: "img",
2721
+ viewBox: "0 0 24 24",
2722
+ width: "24",
2723
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M16.792 3.904A4.989 4.989 0 0 1 21.5 9.122c0 3.072-2.652 4.959-5.197 7.222-2.512 2.243-3.865 3.469-4.303 3.752-.477-.309-2.143-1.823-4.303-3.752C5.141 14.072 2.5 12.167 2.5 9.122a4.989 4.989 0 0 1 4.708-5.218 4.21 4.21 0 0 1 3.675 1.941c.84 1.175.98 1.763 1.12 1.763s.278-.588 1.11-1.766a4.17 4.17 0 0 1 3.679-1.938m0-2a6.04 6.04 0 0 0-4.797 2.127 6.052 6.052 0 0 0-4.787-2.127A6.985 6.985 0 0 0 .5 9.122c0 3.61 2.55 5.827 5.015 7.97.283.246.569.494.853.747l1.027.918a44.998 44.998 0 0 0 3.518 3.018 2 2 0 0 0 2.174 0 45.263 45.263 0 0 0 3.626-3.115l.922-.824c.293-.26.59-.519.885-.774 2.334-2.025 4.98-4.32 4.98-7.94a6.985 6.985 0 0 0-6.708-7.218Z" })
2724
+ });
2725
+ };
2726
+ //#endregion
2727
+ //#region src/instagram-preview/icons/menu.tsx
2728
+ const Menu = () => {
2729
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
2730
+ width: "17",
2731
+ height: "5",
2732
+ viewBox: "0 0 17 5",
2733
+ fill: "none",
2734
+ xmlns: "http://www.w3.org/2000/svg",
2735
+ children: [
2736
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
2737
+ d: "M2.11865 3.5C2.67094 3.5 3.11865 3.05228 3.11865 2.5C3.11865 1.94772 2.67094 1.5 2.11865 1.5C1.56637 1.5 1.11865 1.94772 1.11865 2.5C1.11865 3.05228 1.56637 3.5 2.11865 3.5Z",
2738
+ fill: "black",
2739
+ stroke: "black",
2740
+ strokeWidth: "2"
2741
+ }),
2742
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
2743
+ d: "M8.55933 3.5C9.11161 3.5 9.55933 3.05228 9.55933 2.5C9.55933 1.94772 9.11161 1.5 8.55933 1.5C8.00704 1.5 7.55933 1.94772 7.55933 2.5C7.55933 3.05228 8.00704 3.5 8.55933 3.5Z",
2744
+ fill: "black",
2745
+ stroke: "black",
2746
+ strokeWidth: "2"
2747
+ }),
2748
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
2749
+ d: "M15 3.5C15.5523 3.5 16 3.05228 16 2.5C16 1.94772 15.5523 1.5 15 1.5C14.4477 1.5 14 1.94772 14 2.5C14 3.05228 14.4477 3.5 15 3.5Z",
2750
+ fill: "black",
2751
+ stroke: "black",
2752
+ strokeWidth: "2"
2753
+ })
2754
+ ]
2755
+ });
2756
+ };
2757
+ //#endregion
2758
+ //#region src/instagram-preview/icons/share.tsx
2759
+ const Share = () => {
2760
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
2761
+ color: "rgb(38, 38, 38)",
2762
+ fill: "rgb(38, 38, 38)",
2763
+ height: "24",
2764
+ role: "img",
2765
+ viewBox: "0 0 24 24",
2766
+ width: "24",
2767
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("line", {
2768
+ fill: "none",
2769
+ stroke: "currentColor",
2770
+ strokeLinejoin: "round",
2771
+ strokeWidth: "2",
2772
+ x1: "22",
2773
+ x2: "9.218",
2774
+ y1: "3",
2775
+ y2: "10.083"
2776
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("polygon", {
2777
+ fill: "none",
2778
+ points: "11.698 20.334 22 3.001 2 3.001 9.218 10.084 11.698 20.334",
2779
+ stroke: "currentColor",
2780
+ strokeLinejoin: "round",
2781
+ strokeWidth: "2"
2782
+ })]
2783
+ });
2784
+ };
2785
+ //#endregion
2786
+ //#region src/instagram-preview/post-preview.tsx
2787
+ /**
2788
+ * Instagram Post Preview Component
2789
+ *
2790
+ * @param {InstagramPreviewProps} props - The props for the Instagram post preview.
2791
+ *
2792
+ * @return The Instagram post preview component.
2793
+ */
2794
+ function InstagramPostPreview({ image, imageFocalPoint, media, name, profileImage, caption }) {
2795
+ const username = name || "username";
2796
+ const mediaItem = media?.[0];
2797
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2798
+ className: "instagram-preview__wrapper",
2799
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
2800
+ className: "instagram-preview__container",
2801
+ children: [
2802
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2803
+ className: "instagram-preview__header",
2804
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2805
+ className: "instagram-preview__header--avatar",
2806
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AvatarWithFallback, { src: profileImage })
2807
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2808
+ className: "instagram-preview__header--profile",
2809
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2810
+ className: "instagram-preview__header--profile-name",
2811
+ children: username
2812
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2813
+ className: "instagram-preview__header--profile-menu",
2814
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Menu, {})
2815
+ })]
2816
+ })]
2817
+ }),
2818
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2819
+ className: "instagram-preview__media",
2820
+ children: mediaItem ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2821
+ className: "instagram-preview__media-item",
2822
+ children: mediaItem.type.startsWith("video/") ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("video", {
2823
+ controls: false,
2824
+ className: "instagram-preview__media--video",
2825
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("source", {
2826
+ src: mediaItem.url,
2827
+ type: mediaItem.type
2828
+ })
2829
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
2830
+ className: "instagram-preview__media--image",
2831
+ src: mediaItem.url,
2832
+ alt: ""
2833
+ })
2834
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MediaImage, {
2835
+ className: "instagram-preview__media--image",
2836
+ src: image,
2837
+ alt: "",
2838
+ focalPoint: imageFocalPoint
2839
+ })
2840
+ }),
2841
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2842
+ className: "instagram-preview__content",
2843
+ children: [
2844
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
2845
+ className: "instagram-preview__content--actions",
2846
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2847
+ className: "instagram-preview__content--actions-primary",
2848
+ children: [
2849
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Heart, {}),
2850
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Comment, {}),
2851
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Share, {})
2852
+ ]
2853
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2854
+ className: "instagram-preview__content--actions-secondary",
2855
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Bookmark, {})
2856
+ })]
2857
+ }),
2858
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2859
+ className: "instagram-preview__content--body",
2860
+ children: [
2861
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2862
+ className: "instagram-preview__content--name",
2863
+ children: username
2864
+ }),
2865
+ "\xA0",
2866
+ caption ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2867
+ className: "instagram-preview__content--text",
2868
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ExpandableText, {
2869
+ text: caption,
2870
+ children: (visibleText) => preparePreviewText(visibleText, {
2871
+ platform: "instagram",
2872
+ maxChars: FEED_TEXT_MAX_LENGTH
2873
+ })
2874
+ })
2875
+ }) : null
2876
+ ]
2877
+ }),
2878
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2879
+ className: "instagram-preview__content--footer",
2880
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: (0, _wordpress_i18n.__)("View one comment", "social-previews") })
2881
+ })
2882
+ ]
2883
+ })
2884
+ ]
2885
+ })
2886
+ });
2887
+ }
2888
+ //#endregion
2889
+ //#region src/instagram-preview/previews.tsx
2890
+ const InstagramPreviews = ({ headingLevel, hidePostPreview, ...props }) => {
2891
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2892
+ className: "social-preview instagram-preview",
2893
+ children: !hidePostPreview && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
2894
+ className: "social-preview__section instagram-preview__section",
2895
+ children: [
2896
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SectionHeading, {
2897
+ level: headingLevel,
2898
+ children: (0, _wordpress_i18n.__)("Your post", "social-previews")
2899
+ }),
2900
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2901
+ className: "social-preview__section-desc",
2902
+ children: (0, _wordpress_i18n.__)("This is what your social post will look like on Instagram:", "social-previews")
2903
+ }),
2904
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InstagramPostPreview, { ...props })
2905
+ ]
2906
+ })
2907
+ });
2908
+ };
2909
+ //#endregion
2910
+ exports.AUTO_SHARED_LINK_PREVIEW = AUTO_SHARED_LINK_PREVIEW;
2911
+ exports.AUTO_SHARED_SOCIAL_POST_PREVIEW = AUTO_SHARED_SOCIAL_POST_PREVIEW;
2912
+ exports.BlueskyLinkPreview = BlueskyLinkPreview;
2913
+ exports.BlueskyPostPreview = BlueskyPostPreview;
2914
+ exports.BlueskyPreviews = BlueskyPreviews;
2915
+ exports.DEFAULT_LINK_PREVIEW = DEFAULT_LINK_PREVIEW;
2916
+ exports.FacebookLinkPreview = FacebookLinkPreview;
2917
+ exports.FacebookPostPreview = FacebookPostPreview;
2918
+ exports.FacebookPreviews = FacebookPreviews;
2919
+ exports.GoogleSearchPreview = GoogleSearchPreview;
2920
+ exports.InstagramPostPreview = InstagramPostPreview;
2921
+ exports.InstagramPreviews = InstagramPreviews;
2922
+ exports.LANDSCAPE_MODE = LANDSCAPE_MODE;
2923
+ exports.LinkedInLinkPreview = LinkedInLinkPreview;
2924
+ exports.LinkedInPostPreview = LinkedInPostPreview;
2925
+ exports.LinkedInPreviews = LinkedInPreviews;
2926
+ exports.MastodonLinkPreview = MastodonLinkPreview;
2927
+ exports.MastodonPostPreview = MastodonPostPreview;
2928
+ exports.MastodonPreviews = MastodonPreviews;
2929
+ exports.NextdoorLinkPreview = NextdoorLinkPreview;
2930
+ exports.NextdoorPostPreview = NextdoorPostPreview;
2931
+ exports.NextdoorPreviews = NextdoorPreviews;
2932
+ exports.PORTRAIT_MODE = PORTRAIT_MODE;
2933
+ exports.TYPE_ARTICLE = TYPE_ARTICLE;
2934
+ exports.TYPE_WEBSITE = TYPE_WEBSITE;
2935
+ exports.ThreadsLinkPreview = ThreadsLinkPreview;
2936
+ exports.ThreadsPostPreview = ThreadsPostPreview;
2937
+ exports.ThreadsPreviews = ThreadsPreviews;
2938
+ exports.TumblrLinkPreview = TumblrLinkPreview;
2939
+ exports.TumblrPostPreview = TumblrPostPreview;
2940
+ exports.TumblrPreviews = TumblrPreviews;
2941
+ exports.TwitterLinkPreview = TwitterLinkPreview;
2942
+ exports.TwitterPostPreview = TwitterPostPreview;
2943
+ exports.TwitterPreviews = TwitterPreviews;
2944
+ exports.parseHyperlinks = parseHyperlinks;
2945
+
2946
+ //# sourceMappingURL=index.cjs.map