react-sharesheet 1.0.0 → 1.2.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.
Files changed (45) hide show
  1. package/README.md +84 -102
  2. package/dist/content.d.mts +3 -3
  3. package/dist/content.d.ts +3 -3
  4. package/dist/content.js +296 -271
  5. package/dist/content.js.map +1 -1
  6. package/dist/content.mjs +298 -273
  7. package/dist/content.mjs.map +1 -1
  8. package/dist/drawer.d.mts +3 -3
  9. package/dist/drawer.d.ts +3 -3
  10. package/dist/drawer.js +298 -275
  11. package/dist/drawer.js.map +1 -1
  12. package/dist/drawer.mjs +300 -277
  13. package/dist/drawer.mjs.map +1 -1
  14. package/dist/headless-B7I228Dt.d.mts +98 -0
  15. package/dist/headless-BiSYHizs.d.ts +98 -0
  16. package/dist/headless.d.mts +3 -50
  17. package/dist/headless.d.ts +3 -50
  18. package/dist/headless.js +165 -0
  19. package/dist/headless.js.map +1 -1
  20. package/dist/headless.mjs +163 -1
  21. package/dist/headless.mjs.map +1 -1
  22. package/dist/index.d.mts +2 -2
  23. package/dist/index.d.ts +2 -2
  24. package/dist/index.js +339 -277
  25. package/dist/index.js.map +1 -1
  26. package/dist/index.mjs +329 -278
  27. package/dist/index.mjs.map +1 -1
  28. package/dist/{platforms-DU1DVDFq.d.mts → platforms-omqzPfYX.d.mts} +17 -23
  29. package/dist/{platforms-DU1DVDFq.d.ts → platforms-omqzPfYX.d.ts} +17 -23
  30. package/package.json +24 -7
  31. package/src/ShareSheetContent.tsx +157 -311
  32. package/src/ShareSheetDrawer.tsx +2 -4
  33. package/src/__tests__/hooks.test.ts +203 -0
  34. package/src/__tests__/og-fetcher.test.ts +144 -0
  35. package/src/__tests__/platforms.test.ts +148 -0
  36. package/src/__tests__/setup.ts +22 -0
  37. package/src/__tests__/share-functions.test.ts +152 -0
  38. package/src/__tests__/utils.test.ts +64 -0
  39. package/src/headless.ts +4 -1
  40. package/src/hooks.ts +60 -2
  41. package/src/index.ts +20 -4
  42. package/src/og-fetcher.ts +64 -0
  43. package/src/share-functions.ts +25 -1
  44. package/src/types.ts +17 -24
  45. package/src/utils.ts +125 -0
package/dist/content.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  // src/ShareSheetContent.tsx
2
2
  import { useMemo as useMemo2, useState as useState2, useCallback as useCallback2 } from "react";
3
- import { Image, FileText, Music, Film, Link2, Play } from "lucide-react";
3
+ import { Image, Link2 } from "lucide-react";
4
4
 
5
5
  // src/utils.ts
6
6
  import { clsx } from "clsx";
@@ -14,9 +14,110 @@ function openUrl(url) {
14
14
  function getSafeUrl(shareUrl) {
15
15
  return shareUrl || (typeof window !== "undefined" ? window.location.href : "");
16
16
  }
17
+ function isMobileDevice() {
18
+ if (typeof navigator === "undefined") return false;
19
+ const userAgent = navigator.userAgent || navigator.vendor || "";
20
+ const mobileRegex = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini|Mobile|mobile|CriOS/i;
21
+ const hasTouch = typeof window !== "undefined" && ("ontouchstart" in window || navigator.maxTouchPoints > 0);
22
+ return mobileRegex.test(userAgent);
23
+ }
24
+ var MOBILE_ONLY_PLATFORMS = [
25
+ "instagram",
26
+ "tiktok",
27
+ "threads",
28
+ "sms"
29
+ ];
30
+ function checkPlatformAvailability(platform) {
31
+ const isMobile = isMobileDevice();
32
+ if (MOBILE_ONLY_PLATFORMS.includes(platform)) {
33
+ if (!isMobile) {
34
+ return {
35
+ available: false,
36
+ reason: `${platform} requires a mobile device with the app installed`
37
+ };
38
+ }
39
+ }
40
+ if (platform === "sms" && !isMobile) {
41
+ return {
42
+ available: false,
43
+ reason: "SMS sharing requires a mobile device"
44
+ };
45
+ }
46
+ if (platform === "native") {
47
+ const canShare = typeof navigator !== "undefined" && "share" in navigator;
48
+ if (!canShare) {
49
+ return {
50
+ available: false,
51
+ reason: "Native share is not supported by this browser"
52
+ };
53
+ }
54
+ }
55
+ return { available: true };
56
+ }
57
+ function getAllPlatformAvailability() {
58
+ const platforms = [
59
+ "native",
60
+ "copy",
61
+ "download",
62
+ "whatsapp",
63
+ "telegram",
64
+ "instagram",
65
+ "facebook",
66
+ "snapchat",
67
+ "sms",
68
+ "email",
69
+ "linkedin",
70
+ "reddit",
71
+ "x",
72
+ "tiktok",
73
+ "threads"
74
+ ];
75
+ const result = {};
76
+ for (const platform of platforms) {
77
+ result[platform] = checkPlatformAvailability(platform);
78
+ }
79
+ return result;
80
+ }
81
+ function warnUnavailablePlatform(platform, reason) {
82
+ console.warn(
83
+ `[react-sharesheet] ${platform} sharing is not available: ${reason}. This share option may not work correctly on this device.`
84
+ );
85
+ }
17
86
 
18
87
  // src/hooks.ts
19
- import { useMemo, useState, useCallback } from "react";
88
+ import { useMemo, useState, useCallback, useEffect } from "react";
89
+
90
+ // src/og-fetcher.ts
91
+ var ogCache = /* @__PURE__ */ new Map();
92
+ async function fetchOGData(url) {
93
+ if (ogCache.has(url)) {
94
+ return ogCache.get(url);
95
+ }
96
+ try {
97
+ const apiUrl = `https://api.microlink.io?url=${encodeURIComponent(url)}`;
98
+ const response = await fetch(apiUrl);
99
+ if (!response.ok) {
100
+ throw new Error(`Failed to fetch OG data: ${response.status}`);
101
+ }
102
+ const json = await response.json();
103
+ if (json.status !== "success" || !json.data) {
104
+ return null;
105
+ }
106
+ const { title, description, image, url: canonicalUrl, publisher } = json.data;
107
+ const ogData = {
108
+ title: title || void 0,
109
+ description: description || void 0,
110
+ image: image?.url || void 0,
111
+ url: canonicalUrl || url,
112
+ siteName: publisher || void 0
113
+ };
114
+ ogCache.set(url, ogData);
115
+ return ogData;
116
+ } catch (error) {
117
+ console.warn("[react-sharesheet] Failed to fetch OG data:", error);
118
+ return null;
119
+ }
120
+ }
20
121
 
21
122
  // src/share-functions.ts
22
123
  function shareToWhatsApp(url, text) {
@@ -39,12 +140,24 @@ function shareToFacebook(url) {
39
140
  openUrl(`https://www.facebook.com/sharer/sharer.php?u=${encodedUrl}`);
40
141
  }
41
142
  function openInstagram() {
143
+ const availability = checkPlatformAvailability("instagram");
144
+ if (!availability.available) {
145
+ warnUnavailablePlatform("instagram", availability.reason);
146
+ }
42
147
  window.location.href = "instagram://";
43
148
  }
44
149
  function openTikTok() {
150
+ const availability = checkPlatformAvailability("tiktok");
151
+ if (!availability.available) {
152
+ warnUnavailablePlatform("tiktok", availability.reason);
153
+ }
45
154
  window.location.href = "tiktok://";
46
155
  }
47
156
  function openThreads() {
157
+ const availability = checkPlatformAvailability("threads");
158
+ if (!availability.available) {
159
+ warnUnavailablePlatform("threads", availability.reason);
160
+ }
48
161
  window.location.href = "threads://";
49
162
  }
50
163
  function shareToSnapchat(url) {
@@ -52,6 +165,10 @@ function shareToSnapchat(url) {
52
165
  openUrl(`https://www.snapchat.com/scan?attachmentUrl=${encodedUrl}`);
53
166
  }
54
167
  function shareViaSMS(url, text) {
168
+ const availability = checkPlatformAvailability("sms");
169
+ if (!availability.available) {
170
+ warnUnavailablePlatform("sms", availability.reason);
171
+ }
55
172
  const body = encodeURIComponent(`${text}
56
173
  ${url}`);
57
174
  window.location.href = `sms:?body=${body}`;
@@ -89,6 +206,12 @@ function useShareSheet({
89
206
  const canNativeShare = useMemo(() => {
90
207
  return typeof navigator !== "undefined" && "share" in navigator;
91
208
  }, []);
209
+ const isMobile = useMemo(() => {
210
+ return isMobileDevice();
211
+ }, []);
212
+ const platformAvailability = useMemo(() => {
213
+ return getAllPlatformAvailability();
214
+ }, []);
92
215
  const safeUrl = getSafeUrl(shareUrl);
93
216
  const copyLink = useCallback(async () => {
94
217
  if (!safeUrl) return;
@@ -177,6 +300,8 @@ function useShareSheet({
177
300
  copied,
178
301
  downloading,
179
302
  safeUrl,
303
+ isMobile,
304
+ platformAvailability,
180
305
  copyLink,
181
306
  nativeShare,
182
307
  downloadFile,
@@ -194,6 +319,37 @@ function useShareSheet({
194
319
  shareReddit
195
320
  };
196
321
  }
322
+ function useOGData(url) {
323
+ const [ogData, setOgData] = useState(null);
324
+ const [loading, setLoading] = useState(false);
325
+ const [error, setError] = useState(null);
326
+ useEffect(() => {
327
+ if (!url) {
328
+ setOgData(null);
329
+ setLoading(false);
330
+ setError(null);
331
+ return;
332
+ }
333
+ let cancelled = false;
334
+ setLoading(true);
335
+ setError(null);
336
+ fetchOGData(url).then((data) => {
337
+ if (!cancelled) {
338
+ setOgData(data);
339
+ setLoading(false);
340
+ }
341
+ }).catch((err) => {
342
+ if (!cancelled) {
343
+ setError(err instanceof Error ? err.message : "Failed to fetch OG data");
344
+ setLoading(false);
345
+ }
346
+ });
347
+ return () => {
348
+ cancelled = true;
349
+ };
350
+ }, [url]);
351
+ return { ogData, loading, error };
352
+ }
197
353
 
198
354
  // src/platforms.tsx
199
355
  import {
@@ -345,32 +501,6 @@ var CSS_VAR_DEFAULTS = CSS_VAR_UI_DEFAULTS;
345
501
  import { jsx as jsx2, jsxs } from "react/jsx-runtime";
346
502
  var DEFAULT_BUTTON_SIZE = 45;
347
503
  var DEFAULT_ICON_SIZE = 22;
348
- var IMAGE_EXTENSIONS = ["jpg", "jpeg", "png", "gif", "webp", "svg", "bmp", "ico", "avif"];
349
- var VIDEO_EXTENSIONS = ["mp4", "webm", "mov", "avi", "mkv", "m4v", "ogv"];
350
- var AUDIO_EXTENSIONS = ["mp3", "wav", "ogg", "m4a", "aac", "flac", "wma"];
351
- function detectPreviewType(url) {
352
- try {
353
- const pathname = new URL(url, "http://localhost").pathname;
354
- const ext = pathname.split(".").pop()?.toLowerCase() || "";
355
- if (IMAGE_EXTENSIONS.includes(ext)) return "image";
356
- if (VIDEO_EXTENSIONS.includes(ext)) return "video";
357
- if (AUDIO_EXTENSIONS.includes(ext)) return "audio";
358
- if (url.includes("/api/og") || url.includes("og-image")) return "image";
359
- if (url.includes("youtube.com") || url.includes("vimeo.com")) return "video";
360
- return "link";
361
- } catch {
362
- return "link";
363
- }
364
- }
365
- function getFilenameFromUrl(url) {
366
- try {
367
- const pathname = new URL(url, "http://localhost").pathname;
368
- const filename = pathname.split("/").pop() || "";
369
- return decodeURIComponent(filename);
370
- } catch {
371
- return url;
372
- }
373
- }
374
504
  var defaultClasses = {
375
505
  root: "max-w-md mx-auto",
376
506
  header: "text-center mb-2",
@@ -379,12 +509,8 @@ var defaultClasses = {
379
509
  preview: "flex justify-center mb-4 px-4",
380
510
  previewSkeleton: "rounded-xl overflow-hidden",
381
511
  previewImage: "",
382
- previewVideo: "",
383
- previewFile: "",
384
- previewFileIcon: "",
385
- previewFilename: "truncate",
386
- previewLink: "",
387
- grid: "px-2 py-6 flex flex-row items-center gap-4 gap-y-6 flex-wrap justify-center",
512
+ previewMeta: "",
513
+ grid: "px-2 py-6 flex flex-row items-start gap-4 gap-y-6 flex-wrap justify-center",
388
514
  button: "flex flex-col items-center gap-0 text-xs w-[60px] outline-none cursor-pointer group",
389
515
  buttonIcon: "p-2 rounded-full transition-all flex items-center justify-center group-hover:scale-110 group-active:scale-95 mb-2",
390
516
  buttonLabel: ""
@@ -398,28 +524,10 @@ var shimmerKeyframes = `
398
524
  function cssVar(name, fallback) {
399
525
  return `var(${name}, ${fallback})`;
400
526
  }
401
- function normalizePreview(preview) {
402
- if (!preview) return null;
403
- if (typeof preview === "string") {
404
- const type2 = detectPreviewType(preview);
405
- return {
406
- url: preview,
407
- type: type2,
408
- filename: getFilenameFromUrl(preview)
409
- };
410
- }
411
- const type = preview.type === "auto" || !preview.type ? detectPreviewType(preview.url) : preview.type;
412
- return {
413
- ...preview,
414
- type,
415
- filename: preview.filename || getFilenameFromUrl(preview.url)
416
- };
417
- }
418
527
  function ShareSheetContent({
419
528
  title = "Share",
420
529
  shareUrl,
421
530
  shareText,
422
- preview,
423
531
  downloadUrl,
424
532
  downloadFilename,
425
533
  className,
@@ -434,15 +542,15 @@ function ShareSheetContent({
434
542
  labels = {},
435
543
  icons = {}
436
544
  }) {
437
- const [mediaLoaded, setMediaLoaded] = useState2(false);
438
- const [mediaError, setMediaError] = useState2(false);
439
- const handleMediaLoad = useCallback2(() => {
440
- setMediaLoaded(true);
545
+ const [imageLoaded, setImageLoaded] = useState2(false);
546
+ const [imageError, setImageError] = useState2(false);
547
+ const { ogData, loading: ogLoading } = useOGData(shareUrl);
548
+ const handleImageLoad = useCallback2(() => {
549
+ setImageLoaded(true);
441
550
  }, []);
442
- const handleMediaError = useCallback2(() => {
443
- setMediaError(true);
551
+ const handleImageError = useCallback2(() => {
552
+ setImageError(true);
444
553
  }, []);
445
- const previewConfig = useMemo2(() => normalizePreview(preview), [preview]);
446
554
  const shareSheet = useShareSheet({
447
555
  shareUrl,
448
556
  shareText,
@@ -478,6 +586,15 @@ function ShareSheetContent({
478
586
  return PLATFORM_IDS.map((id) => {
479
587
  const Icon = PLATFORM_ICONS[id];
480
588
  const defaultLabel = dynamicLabels[id] ?? PLATFORM_LABELS[id];
589
+ const availability = shareSheet.platformAvailability[id];
590
+ let condition = true;
591
+ if (id === "native") {
592
+ condition = shareSheet.canNativeShare;
593
+ } else if (id === "download") {
594
+ condition = !!downloadUrl;
595
+ } else if (!availability.available) {
596
+ condition = false;
597
+ }
481
598
  return {
482
599
  id,
483
600
  label: labels[id] ?? defaultLabel,
@@ -486,11 +603,10 @@ function ShareSheetContent({
486
603
  bgColor: cssVar(PLATFORM_CSS_VARS[id], PLATFORM_COLORS[id].bg),
487
604
  textColor: PLATFORM_COLORS[id].text,
488
605
  onClick: shareActions[id],
489
- // Conditions for showing certain buttons
490
- condition: id === "native" ? shareSheet.canNativeShare : id === "download" ? !!downloadUrl : true
606
+ condition
491
607
  };
492
608
  });
493
- }, [iconSize, labels, icons, dynamicLabels, shareActions, shareSheet.canNativeShare, downloadUrl]);
609
+ }, [iconSize, labels, icons, dynamicLabels, shareActions, shareSheet.canNativeShare, shareSheet.platformAvailability, downloadUrl]);
494
610
  const visibleButtons = useMemo2(() => {
495
611
  return buttons.filter((btn) => {
496
612
  if (btn.condition === false) return false;
@@ -499,49 +615,30 @@ function ShareSheetContent({
499
615
  return true;
500
616
  });
501
617
  }, [buttons, show, hide]);
502
- const showPreview = !!previewConfig;
618
+ const bgColor = cssVar(CSS_VARS_UI.previewBg, CSS_VAR_UI_DEFAULTS[CSS_VARS_UI.previewBg]);
619
+ const shimmerColor = cssVar(CSS_VARS_UI.previewShimmer, CSS_VAR_UI_DEFAULTS[CSS_VARS_UI.previewShimmer]);
620
+ const textColor = cssVar(CSS_VARS_UI.subtitleColor, CSS_VAR_UI_DEFAULTS[CSS_VARS_UI.subtitleColor]);
503
621
  const renderPreview = () => {
504
- if (!previewConfig) return null;
505
- const { type, url, filename, alt, poster } = previewConfig;
506
- const bgColor = cssVar(CSS_VARS_UI.previewBg, CSS_VAR_UI_DEFAULTS[CSS_VARS_UI.previewBg]);
507
- const shimmerColor = cssVar(CSS_VARS_UI.previewShimmer, CSS_VAR_UI_DEFAULTS[CSS_VARS_UI.previewShimmer]);
508
- const textColor = cssVar(CSS_VARS_UI.subtitleColor, CSS_VAR_UI_DEFAULTS[CSS_VARS_UI.subtitleColor]);
509
- const UrlLabel = ({ displayUrl = url }) => /* @__PURE__ */ jsx2(
510
- "div",
511
- {
512
- className: cn(defaultClasses.previewFilename, classNames.previewFilename),
513
- style: {
514
- color: textColor,
515
- fontSize: "10px",
516
- opacity: 0.5,
517
- textAlign: "center",
518
- marginTop: "6px"
519
- },
520
- children: displayUrl
521
- }
522
- );
523
- const PlaceholderCard = ({
524
- icon: IconComponent,
525
- isLoading = false,
526
- label,
527
- displayUrl
528
- }) => /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", alignItems: "center" }, children: [
529
- /* @__PURE__ */ jsxs(
622
+ const ogImage = ogData?.image;
623
+ const hasImage = ogImage && !imageError;
624
+ if (ogLoading) {
625
+ return /* @__PURE__ */ jsx2("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", width: "100%" }, children: /* @__PURE__ */ jsxs(
530
626
  "div",
531
627
  {
532
628
  className: cn(defaultClasses.previewSkeleton, classNames.previewSkeleton),
533
629
  style: {
534
630
  position: "relative",
535
631
  backgroundColor: bgColor,
536
- width: "200px",
537
- height: "120px",
632
+ width: "100%",
633
+ maxWidth: "320px",
634
+ aspectRatio: "1.91 / 1",
538
635
  overflow: "hidden",
539
636
  display: "flex",
540
637
  alignItems: "center",
541
638
  justifyContent: "center"
542
639
  },
543
640
  children: [
544
- isLoading && /* @__PURE__ */ jsx2("div", { style: { position: "absolute", inset: 0, overflow: "hidden" }, children: /* @__PURE__ */ jsx2(
641
+ /* @__PURE__ */ jsx2("div", { style: { position: "absolute", inset: 0, overflow: "hidden" }, children: /* @__PURE__ */ jsx2(
545
642
  "div",
546
643
  {
547
644
  style: {
@@ -552,197 +649,125 @@ function ShareSheetContent({
552
649
  }
553
650
  }
554
651
  ) }),
555
- /* @__PURE__ */ jsxs(
556
- "div",
557
- {
558
- style: {
559
- display: "flex",
560
- flexDirection: "column",
561
- alignItems: "center",
562
- justifyContent: "center",
563
- gap: "8px"
564
- },
565
- children: [
566
- /* @__PURE__ */ jsx2(IconComponent, { size: 32, style: { color: textColor, opacity: 0.4 } }),
567
- label && /* @__PURE__ */ jsx2("span", { style: { color: textColor, fontSize: "11px", opacity: 0.4 }, children: label })
568
- ]
569
- }
570
- )
652
+ /* @__PURE__ */ jsx2(Link2, { size: 32, style: { color: textColor, opacity: 0.4 } })
571
653
  ]
572
654
  }
573
- ),
574
- /* @__PURE__ */ jsx2(UrlLabel, { displayUrl })
575
- ] });
576
- if (mediaError && (type === "image" || type === "video")) {
577
- return /* @__PURE__ */ jsx2(PlaceholderCard, { icon: Link2, displayUrl: url });
655
+ ) });
578
656
  }
579
- switch (type) {
580
- case "image":
581
- if (!mediaLoaded) {
582
- return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", alignItems: "center" }, children: [
583
- /* @__PURE__ */ jsxs(
584
- "div",
585
- {
586
- className: cn(defaultClasses.previewSkeleton, classNames.previewSkeleton),
587
- style: {
588
- position: "relative",
589
- backgroundColor: bgColor,
590
- width: "200px",
591
- height: "120px",
592
- overflow: "hidden",
593
- display: "flex",
594
- alignItems: "center",
595
- justifyContent: "center"
596
- },
597
- children: [
598
- /* @__PURE__ */ jsx2("div", { style: { position: "absolute", inset: 0, overflow: "hidden" }, children: /* @__PURE__ */ jsx2(
599
- "div",
600
- {
601
- style: {
602
- position: "absolute",
603
- inset: 0,
604
- background: `linear-gradient(90deg, transparent, ${shimmerColor}, transparent)`,
605
- animation: "sharesheet-shimmer 1.5s infinite"
606
- }
607
- }
608
- ) }),
609
- /* @__PURE__ */ jsx2(Image, { size: 32, style: { color: textColor, opacity: 0.4 } })
610
- ]
611
- }
612
- ),
613
- /* @__PURE__ */ jsx2(UrlLabel, {}),
614
- /* @__PURE__ */ jsx2(
615
- "img",
616
- {
617
- src: url,
618
- alt: alt || "Preview",
619
- onLoad: handleMediaLoad,
620
- onError: handleMediaError,
621
- style: { display: "none" }
622
- }
623
- )
624
- ] });
625
- }
626
- return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", alignItems: "center" }, children: [
627
- /* @__PURE__ */ jsx2(
628
- "img",
657
+ if (!ogData || !hasImage) {
658
+ return /* @__PURE__ */ jsx2("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", width: "100%" }, children: /* @__PURE__ */ jsx2(
659
+ "div",
660
+ {
661
+ className: cn(defaultClasses.previewSkeleton, classNames.previewSkeleton),
662
+ style: {
663
+ position: "relative",
664
+ backgroundColor: bgColor,
665
+ width: "100%",
666
+ maxWidth: "320px",
667
+ aspectRatio: "1.91 / 1",
668
+ overflow: "hidden",
669
+ display: "flex",
670
+ alignItems: "center",
671
+ justifyContent: "center"
672
+ },
673
+ children: /* @__PURE__ */ jsxs(
674
+ "div",
629
675
  {
630
- src: url,
631
- alt: alt || "Preview",
632
- className: cn(defaultClasses.previewImage, classNames.previewImage),
633
676
  style: {
634
- maxWidth: "100%",
635
- maxHeight: "180px",
636
- borderRadius: "12px",
637
- opacity: 1,
638
- transition: "opacity 0.3s ease-in-out"
639
- }
640
- }
641
- ),
642
- /* @__PURE__ */ jsx2(UrlLabel, {})
643
- ] });
644
- case "video":
645
- if (!mediaLoaded) {
646
- return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", alignItems: "center" }, children: [
647
- /* @__PURE__ */ jsxs(
648
- "div",
649
- {
650
- className: cn(defaultClasses.previewSkeleton, classNames.previewSkeleton),
651
- style: {
652
- position: "relative",
653
- backgroundColor: bgColor,
654
- width: "200px",
655
- height: "120px",
656
- overflow: "hidden",
657
- display: "flex",
658
- alignItems: "center",
659
- justifyContent: "center"
660
- },
661
- children: [
662
- /* @__PURE__ */ jsx2("div", { style: { position: "absolute", inset: 0, overflow: "hidden" }, children: /* @__PURE__ */ jsx2(
663
- "div",
664
- {
665
- style: {
666
- position: "absolute",
667
- inset: 0,
668
- background: `linear-gradient(90deg, transparent, ${shimmerColor}, transparent)`,
669
- animation: "sharesheet-shimmer 1.5s infinite"
670
- }
671
- }
672
- ) }),
673
- /* @__PURE__ */ jsx2(Film, { size: 32, style: { color: textColor, opacity: 0.4 } })
674
- ]
675
- }
676
- ),
677
- /* @__PURE__ */ jsx2(UrlLabel, {}),
678
- /* @__PURE__ */ jsx2(
679
- "video",
680
- {
681
- src: url,
682
- poster,
683
- onLoadedData: handleMediaLoad,
684
- onError: handleMediaError,
685
- style: { display: "none" },
686
- muted: true,
687
- playsInline: true,
688
- preload: "metadata"
689
- }
690
- )
691
- ] });
692
- }
693
- return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", alignItems: "center" }, children: [
694
- /* @__PURE__ */ jsxs("div", { style: { position: "relative", borderRadius: "12px", overflow: "hidden" }, children: [
695
- /* @__PURE__ */ jsx2(
696
- "video",
697
- {
698
- src: url,
699
- poster,
700
- className: cn(defaultClasses.previewVideo, classNames.previewVideo),
701
- style: {
702
- maxWidth: "100%",
703
- maxHeight: "180px",
704
- display: "block"
705
- },
706
- muted: true,
707
- playsInline: true,
708
- preload: "metadata"
709
- }
710
- ),
711
- /* @__PURE__ */ jsx2(
712
- "div",
713
- {
714
- style: {
715
- position: "absolute",
716
- inset: 0,
717
- display: "flex",
718
- alignItems: "center",
719
- justifyContent: "center",
720
- pointerEvents: "none"
721
- },
722
- children: /* @__PURE__ */ jsx2(
723
- "div",
677
+ display: "flex",
678
+ flexDirection: "column",
679
+ alignItems: "center",
680
+ justifyContent: "center",
681
+ gap: "8px",
682
+ padding: "16px"
683
+ },
684
+ children: [
685
+ /* @__PURE__ */ jsx2(Link2, { size: 32, style: { color: textColor, opacity: 0.4 } }),
686
+ ogData?.title && /* @__PURE__ */ jsx2(
687
+ "span",
724
688
  {
725
689
  style: {
726
- backgroundColor: "rgba(0, 0, 0, 0.5)",
727
- borderRadius: "50%",
728
- padding: "10px"
690
+ color: textColor,
691
+ fontSize: "12px",
692
+ opacity: 0.6,
693
+ textAlign: "center",
694
+ maxWidth: "280px",
695
+ overflow: "hidden",
696
+ textOverflow: "ellipsis",
697
+ display: "-webkit-box",
698
+ WebkitLineClamp: 2,
699
+ WebkitBoxOrient: "vertical"
729
700
  },
730
- children: /* @__PURE__ */ jsx2(Play, { size: 20, fill: "white", color: "white" })
701
+ children: ogData.title
731
702
  }
732
703
  )
733
- }
734
- )
735
- ] }),
736
- /* @__PURE__ */ jsx2(UrlLabel, {})
737
- ] });
738
- case "audio":
739
- return /* @__PURE__ */ jsx2(PlaceholderCard, { icon: Music, label: filename || "Audio", displayUrl: url });
740
- case "file":
741
- return /* @__PURE__ */ jsx2(PlaceholderCard, { icon: FileText, label: filename || "File", displayUrl: url });
742
- case "link":
743
- default:
744
- return /* @__PURE__ */ jsx2(PlaceholderCard, { icon: Link2, displayUrl: url });
704
+ ]
705
+ }
706
+ )
707
+ }
708
+ ) });
745
709
  }
710
+ if (!imageLoaded) {
711
+ return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", width: "100%" }, children: [
712
+ /* @__PURE__ */ jsxs(
713
+ "div",
714
+ {
715
+ className: cn(defaultClasses.previewSkeleton, classNames.previewSkeleton),
716
+ style: {
717
+ position: "relative",
718
+ backgroundColor: bgColor,
719
+ width: "100%",
720
+ maxWidth: "320px",
721
+ aspectRatio: "1.91 / 1",
722
+ overflow: "hidden",
723
+ display: "flex",
724
+ alignItems: "center",
725
+ justifyContent: "center"
726
+ },
727
+ children: [
728
+ /* @__PURE__ */ jsx2("div", { style: { position: "absolute", inset: 0, overflow: "hidden" }, children: /* @__PURE__ */ jsx2(
729
+ "div",
730
+ {
731
+ style: {
732
+ position: "absolute",
733
+ inset: 0,
734
+ background: `linear-gradient(90deg, transparent, ${shimmerColor}, transparent)`,
735
+ animation: "sharesheet-shimmer 1.5s infinite"
736
+ }
737
+ }
738
+ ) }),
739
+ /* @__PURE__ */ jsx2(Image, { size: 32, style: { color: textColor, opacity: 0.4 } })
740
+ ]
741
+ }
742
+ ),
743
+ /* @__PURE__ */ jsx2(
744
+ "img",
745
+ {
746
+ src: ogImage,
747
+ alt: ogData.title || "Preview",
748
+ onLoad: handleImageLoad,
749
+ onError: handleImageError,
750
+ style: { display: "none" }
751
+ }
752
+ )
753
+ ] });
754
+ }
755
+ return /* @__PURE__ */ jsx2("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", width: "100%" }, children: /* @__PURE__ */ jsx2(
756
+ "img",
757
+ {
758
+ src: ogImage,
759
+ alt: ogData.title || "Preview",
760
+ className: cn(defaultClasses.previewImage, classNames.previewImage),
761
+ style: {
762
+ width: "100%",
763
+ maxWidth: "320px",
764
+ height: "auto",
765
+ borderRadius: "12px",
766
+ opacity: 1,
767
+ transition: "opacity 0.3s ease-in-out"
768
+ }
769
+ }
770
+ ) });
746
771
  };
747
772
  return /* @__PURE__ */ jsxs("div", { className: cn(defaultClasses.root, classNames.root, className), children: [
748
773
  /* @__PURE__ */ jsx2("style", { dangerouslySetInnerHTML: { __html: shimmerKeyframes } }),
@@ -764,7 +789,7 @@ function ShareSheetContent({
764
789
  }
765
790
  )
766
791
  ] }),
767
- showPreview && /* @__PURE__ */ jsx2("div", { className: cn(defaultClasses.preview, classNames.preview), children: renderPreview() }),
792
+ /* @__PURE__ */ jsx2("div", { className: cn(defaultClasses.preview, classNames.preview), children: renderPreview() }),
768
793
  /* @__PURE__ */ jsx2("div", { className: cn(defaultClasses.grid, classNames.grid), children: visibleButtons.map((btn) => /* @__PURE__ */ jsxs(
769
794
  "button",
770
795
  {