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/index.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,127 @@ 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
+ function isIOSDevice() {
25
+ if (typeof navigator === "undefined") return false;
26
+ const userAgent = navigator.userAgent || "";
27
+ return /iPhone|iPad|iPod/i.test(userAgent);
28
+ }
29
+ function isAndroidDevice() {
30
+ if (typeof navigator === "undefined") return false;
31
+ const userAgent = navigator.userAgent || "";
32
+ return /Android/i.test(userAgent);
33
+ }
34
+ var MOBILE_ONLY_PLATFORMS = [
35
+ "instagram",
36
+ "tiktok",
37
+ "threads",
38
+ "sms"
39
+ ];
40
+ var MOBILE_PREFERRED_PLATFORMS = [
41
+ "snapchat",
42
+ "whatsapp"
43
+ ];
44
+ function checkPlatformAvailability(platform) {
45
+ const isMobile = isMobileDevice();
46
+ if (MOBILE_ONLY_PLATFORMS.includes(platform)) {
47
+ if (!isMobile) {
48
+ return {
49
+ available: false,
50
+ reason: `${platform} requires a mobile device with the app installed`
51
+ };
52
+ }
53
+ }
54
+ if (platform === "sms" && !isMobile) {
55
+ return {
56
+ available: false,
57
+ reason: "SMS sharing requires a mobile device"
58
+ };
59
+ }
60
+ if (platform === "native") {
61
+ const canShare = typeof navigator !== "undefined" && "share" in navigator;
62
+ if (!canShare) {
63
+ return {
64
+ available: false,
65
+ reason: "Native share is not supported by this browser"
66
+ };
67
+ }
68
+ }
69
+ return { available: true };
70
+ }
71
+ function getAllPlatformAvailability() {
72
+ const platforms = [
73
+ "native",
74
+ "copy",
75
+ "download",
76
+ "whatsapp",
77
+ "telegram",
78
+ "instagram",
79
+ "facebook",
80
+ "snapchat",
81
+ "sms",
82
+ "email",
83
+ "linkedin",
84
+ "reddit",
85
+ "x",
86
+ "tiktok",
87
+ "threads"
88
+ ];
89
+ const result = {};
90
+ for (const platform of platforms) {
91
+ result[platform] = checkPlatformAvailability(platform);
92
+ }
93
+ return result;
94
+ }
95
+ function warnUnavailablePlatform(platform, reason) {
96
+ console.warn(
97
+ `[react-sharesheet] ${platform} sharing is not available: ${reason}. This share option may not work correctly on this device.`
98
+ );
99
+ }
17
100
 
18
101
  // src/hooks.ts
19
- import { useMemo, useState, useCallback } from "react";
102
+ import { useMemo, useState, useCallback, useEffect } from "react";
103
+
104
+ // src/og-fetcher.ts
105
+ var ogCache = /* @__PURE__ */ new Map();
106
+ async function fetchOGData(url) {
107
+ if (ogCache.has(url)) {
108
+ return ogCache.get(url);
109
+ }
110
+ try {
111
+ const apiUrl = `https://api.microlink.io?url=${encodeURIComponent(url)}`;
112
+ const response = await fetch(apiUrl);
113
+ if (!response.ok) {
114
+ throw new Error(`Failed to fetch OG data: ${response.status}`);
115
+ }
116
+ const json = await response.json();
117
+ if (json.status !== "success" || !json.data) {
118
+ return null;
119
+ }
120
+ const { title, description, image, url: canonicalUrl, publisher } = json.data;
121
+ const ogData = {
122
+ title: title || void 0,
123
+ description: description || void 0,
124
+ image: image?.url || void 0,
125
+ url: canonicalUrl || url,
126
+ siteName: publisher || void 0
127
+ };
128
+ ogCache.set(url, ogData);
129
+ return ogData;
130
+ } catch (error) {
131
+ console.warn("[react-sharesheet] Failed to fetch OG data:", error);
132
+ return null;
133
+ }
134
+ }
135
+ function clearOGCache() {
136
+ ogCache.clear();
137
+ }
20
138
 
21
139
  // src/share-functions.ts
22
140
  function shareToWhatsApp(url, text) {
@@ -39,12 +157,24 @@ function shareToFacebook(url) {
39
157
  openUrl(`https://www.facebook.com/sharer/sharer.php?u=${encodedUrl}`);
40
158
  }
41
159
  function openInstagram() {
160
+ const availability = checkPlatformAvailability("instagram");
161
+ if (!availability.available) {
162
+ warnUnavailablePlatform("instagram", availability.reason);
163
+ }
42
164
  window.location.href = "instagram://";
43
165
  }
44
166
  function openTikTok() {
167
+ const availability = checkPlatformAvailability("tiktok");
168
+ if (!availability.available) {
169
+ warnUnavailablePlatform("tiktok", availability.reason);
170
+ }
45
171
  window.location.href = "tiktok://";
46
172
  }
47
173
  function openThreads() {
174
+ const availability = checkPlatformAvailability("threads");
175
+ if (!availability.available) {
176
+ warnUnavailablePlatform("threads", availability.reason);
177
+ }
48
178
  window.location.href = "threads://";
49
179
  }
50
180
  function shareToSnapchat(url) {
@@ -52,6 +182,10 @@ function shareToSnapchat(url) {
52
182
  openUrl(`https://www.snapchat.com/scan?attachmentUrl=${encodedUrl}`);
53
183
  }
54
184
  function shareViaSMS(url, text) {
185
+ const availability = checkPlatformAvailability("sms");
186
+ if (!availability.available) {
187
+ warnUnavailablePlatform("sms", availability.reason);
188
+ }
55
189
  const body = encodeURIComponent(`${text}
56
190
  ${url}`);
57
191
  window.location.href = `sms:?body=${body}`;
@@ -89,6 +223,12 @@ function useShareSheet({
89
223
  const canNativeShare = useMemo(() => {
90
224
  return typeof navigator !== "undefined" && "share" in navigator;
91
225
  }, []);
226
+ const isMobile = useMemo(() => {
227
+ return isMobileDevice();
228
+ }, []);
229
+ const platformAvailability = useMemo(() => {
230
+ return getAllPlatformAvailability();
231
+ }, []);
92
232
  const safeUrl = getSafeUrl(shareUrl);
93
233
  const copyLink = useCallback(async () => {
94
234
  if (!safeUrl) return;
@@ -177,6 +317,8 @@ function useShareSheet({
177
317
  copied,
178
318
  downloading,
179
319
  safeUrl,
320
+ isMobile,
321
+ platformAvailability,
180
322
  copyLink,
181
323
  nativeShare,
182
324
  downloadFile,
@@ -194,6 +336,37 @@ function useShareSheet({
194
336
  shareReddit
195
337
  };
196
338
  }
339
+ function useOGData(url) {
340
+ const [ogData, setOgData] = useState(null);
341
+ const [loading, setLoading] = useState(false);
342
+ const [error, setError] = useState(null);
343
+ useEffect(() => {
344
+ if (!url) {
345
+ setOgData(null);
346
+ setLoading(false);
347
+ setError(null);
348
+ return;
349
+ }
350
+ let cancelled = false;
351
+ setLoading(true);
352
+ setError(null);
353
+ fetchOGData(url).then((data) => {
354
+ if (!cancelled) {
355
+ setOgData(data);
356
+ setLoading(false);
357
+ }
358
+ }).catch((err) => {
359
+ if (!cancelled) {
360
+ setError(err instanceof Error ? err.message : "Failed to fetch OG data");
361
+ setLoading(false);
362
+ }
363
+ });
364
+ return () => {
365
+ cancelled = true;
366
+ };
367
+ }, [url]);
368
+ return { ogData, loading, error };
369
+ }
197
370
  var useShareMenu = useShareSheet;
198
371
 
199
372
  // src/platforms.tsx
@@ -368,32 +541,6 @@ var CSS_VAR_DEFAULTS = CSS_VAR_UI_DEFAULTS;
368
541
  import { jsx as jsx2, jsxs } from "react/jsx-runtime";
369
542
  var DEFAULT_BUTTON_SIZE = 45;
370
543
  var DEFAULT_ICON_SIZE = 22;
371
- var IMAGE_EXTENSIONS = ["jpg", "jpeg", "png", "gif", "webp", "svg", "bmp", "ico", "avif"];
372
- var VIDEO_EXTENSIONS = ["mp4", "webm", "mov", "avi", "mkv", "m4v", "ogv"];
373
- var AUDIO_EXTENSIONS = ["mp3", "wav", "ogg", "m4a", "aac", "flac", "wma"];
374
- function detectPreviewType(url) {
375
- try {
376
- const pathname = new URL(url, "http://localhost").pathname;
377
- const ext = pathname.split(".").pop()?.toLowerCase() || "";
378
- if (IMAGE_EXTENSIONS.includes(ext)) return "image";
379
- if (VIDEO_EXTENSIONS.includes(ext)) return "video";
380
- if (AUDIO_EXTENSIONS.includes(ext)) return "audio";
381
- if (url.includes("/api/og") || url.includes("og-image")) return "image";
382
- if (url.includes("youtube.com") || url.includes("vimeo.com")) return "video";
383
- return "link";
384
- } catch {
385
- return "link";
386
- }
387
- }
388
- function getFilenameFromUrl(url) {
389
- try {
390
- const pathname = new URL(url, "http://localhost").pathname;
391
- const filename = pathname.split("/").pop() || "";
392
- return decodeURIComponent(filename);
393
- } catch {
394
- return url;
395
- }
396
- }
397
544
  var defaultClasses = {
398
545
  root: "max-w-md mx-auto",
399
546
  header: "text-center mb-2",
@@ -402,12 +549,8 @@ var defaultClasses = {
402
549
  preview: "flex justify-center mb-4 px-4",
403
550
  previewSkeleton: "rounded-xl overflow-hidden",
404
551
  previewImage: "",
405
- previewVideo: "",
406
- previewFile: "",
407
- previewFileIcon: "",
408
- previewFilename: "truncate",
409
- previewLink: "",
410
- grid: "px-2 py-6 flex flex-row items-center gap-4 gap-y-6 flex-wrap justify-center",
552
+ previewMeta: "",
553
+ grid: "px-2 py-6 flex flex-row items-start gap-4 gap-y-6 flex-wrap justify-center",
411
554
  button: "flex flex-col items-center gap-0 text-xs w-[60px] outline-none cursor-pointer group",
412
555
  buttonIcon: "p-2 rounded-full transition-all flex items-center justify-center group-hover:scale-110 group-active:scale-95 mb-2",
413
556
  buttonLabel: ""
@@ -421,28 +564,10 @@ var shimmerKeyframes = `
421
564
  function cssVar(name, fallback) {
422
565
  return `var(${name}, ${fallback})`;
423
566
  }
424
- function normalizePreview(preview) {
425
- if (!preview) return null;
426
- if (typeof preview === "string") {
427
- const type2 = detectPreviewType(preview);
428
- return {
429
- url: preview,
430
- type: type2,
431
- filename: getFilenameFromUrl(preview)
432
- };
433
- }
434
- const type = preview.type === "auto" || !preview.type ? detectPreviewType(preview.url) : preview.type;
435
- return {
436
- ...preview,
437
- type,
438
- filename: preview.filename || getFilenameFromUrl(preview.url)
439
- };
440
- }
441
567
  function ShareSheetContent({
442
568
  title = "Share",
443
569
  shareUrl,
444
570
  shareText,
445
- preview,
446
571
  downloadUrl,
447
572
  downloadFilename,
448
573
  className,
@@ -457,15 +582,15 @@ function ShareSheetContent({
457
582
  labels = {},
458
583
  icons = {}
459
584
  }) {
460
- const [mediaLoaded, setMediaLoaded] = useState2(false);
461
- const [mediaError, setMediaError] = useState2(false);
462
- const handleMediaLoad = useCallback2(() => {
463
- setMediaLoaded(true);
585
+ const [imageLoaded, setImageLoaded] = useState2(false);
586
+ const [imageError, setImageError] = useState2(false);
587
+ const { ogData, loading: ogLoading } = useOGData(shareUrl);
588
+ const handleImageLoad = useCallback2(() => {
589
+ setImageLoaded(true);
464
590
  }, []);
465
- const handleMediaError = useCallback2(() => {
466
- setMediaError(true);
591
+ const handleImageError = useCallback2(() => {
592
+ setImageError(true);
467
593
  }, []);
468
- const previewConfig = useMemo2(() => normalizePreview(preview), [preview]);
469
594
  const shareSheet = useShareSheet({
470
595
  shareUrl,
471
596
  shareText,
@@ -501,6 +626,15 @@ function ShareSheetContent({
501
626
  return PLATFORM_IDS.map((id) => {
502
627
  const Icon = PLATFORM_ICONS[id];
503
628
  const defaultLabel = dynamicLabels[id] ?? PLATFORM_LABELS[id];
629
+ const availability = shareSheet.platformAvailability[id];
630
+ let condition = true;
631
+ if (id === "native") {
632
+ condition = shareSheet.canNativeShare;
633
+ } else if (id === "download") {
634
+ condition = !!downloadUrl;
635
+ } else if (!availability.available) {
636
+ condition = false;
637
+ }
504
638
  return {
505
639
  id,
506
640
  label: labels[id] ?? defaultLabel,
@@ -509,11 +643,10 @@ function ShareSheetContent({
509
643
  bgColor: cssVar(PLATFORM_CSS_VARS[id], PLATFORM_COLORS[id].bg),
510
644
  textColor: PLATFORM_COLORS[id].text,
511
645
  onClick: shareActions[id],
512
- // Conditions for showing certain buttons
513
- condition: id === "native" ? shareSheet.canNativeShare : id === "download" ? !!downloadUrl : true
646
+ condition
514
647
  };
515
648
  });
516
- }, [iconSize, labels, icons, dynamicLabels, shareActions, shareSheet.canNativeShare, downloadUrl]);
649
+ }, [iconSize, labels, icons, dynamicLabels, shareActions, shareSheet.canNativeShare, shareSheet.platformAvailability, downloadUrl]);
517
650
  const visibleButtons = useMemo2(() => {
518
651
  return buttons.filter((btn) => {
519
652
  if (btn.condition === false) return false;
@@ -522,49 +655,30 @@ function ShareSheetContent({
522
655
  return true;
523
656
  });
524
657
  }, [buttons, show, hide]);
525
- const showPreview = !!previewConfig;
658
+ const bgColor = cssVar(CSS_VARS_UI.previewBg, CSS_VAR_UI_DEFAULTS[CSS_VARS_UI.previewBg]);
659
+ const shimmerColor = cssVar(CSS_VARS_UI.previewShimmer, CSS_VAR_UI_DEFAULTS[CSS_VARS_UI.previewShimmer]);
660
+ const textColor = cssVar(CSS_VARS_UI.subtitleColor, CSS_VAR_UI_DEFAULTS[CSS_VARS_UI.subtitleColor]);
526
661
  const renderPreview = () => {
527
- if (!previewConfig) return null;
528
- const { type, url, filename, alt, poster } = previewConfig;
529
- const bgColor = cssVar(CSS_VARS_UI.previewBg, CSS_VAR_UI_DEFAULTS[CSS_VARS_UI.previewBg]);
530
- const shimmerColor = cssVar(CSS_VARS_UI.previewShimmer, CSS_VAR_UI_DEFAULTS[CSS_VARS_UI.previewShimmer]);
531
- const textColor = cssVar(CSS_VARS_UI.subtitleColor, CSS_VAR_UI_DEFAULTS[CSS_VARS_UI.subtitleColor]);
532
- const UrlLabel = ({ displayUrl = url }) => /* @__PURE__ */ jsx2(
533
- "div",
534
- {
535
- className: cn(defaultClasses.previewFilename, classNames.previewFilename),
536
- style: {
537
- color: textColor,
538
- fontSize: "10px",
539
- opacity: 0.5,
540
- textAlign: "center",
541
- marginTop: "6px"
542
- },
543
- children: displayUrl
544
- }
545
- );
546
- const PlaceholderCard = ({
547
- icon: IconComponent,
548
- isLoading = false,
549
- label,
550
- displayUrl
551
- }) => /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", alignItems: "center" }, children: [
552
- /* @__PURE__ */ jsxs(
662
+ const ogImage = ogData?.image;
663
+ const hasImage = ogImage && !imageError;
664
+ if (ogLoading) {
665
+ return /* @__PURE__ */ jsx2("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", width: "100%" }, children: /* @__PURE__ */ jsxs(
553
666
  "div",
554
667
  {
555
668
  className: cn(defaultClasses.previewSkeleton, classNames.previewSkeleton),
556
669
  style: {
557
670
  position: "relative",
558
671
  backgroundColor: bgColor,
559
- width: "200px",
560
- height: "120px",
672
+ width: "100%",
673
+ maxWidth: "320px",
674
+ aspectRatio: "1.91 / 1",
561
675
  overflow: "hidden",
562
676
  display: "flex",
563
677
  alignItems: "center",
564
678
  justifyContent: "center"
565
679
  },
566
680
  children: [
567
- isLoading && /* @__PURE__ */ jsx2("div", { style: { position: "absolute", inset: 0, overflow: "hidden" }, children: /* @__PURE__ */ jsx2(
681
+ /* @__PURE__ */ jsx2("div", { style: { position: "absolute", inset: 0, overflow: "hidden" }, children: /* @__PURE__ */ jsx2(
568
682
  "div",
569
683
  {
570
684
  style: {
@@ -575,197 +689,125 @@ function ShareSheetContent({
575
689
  }
576
690
  }
577
691
  ) }),
578
- /* @__PURE__ */ jsxs(
579
- "div",
580
- {
581
- style: {
582
- display: "flex",
583
- flexDirection: "column",
584
- alignItems: "center",
585
- justifyContent: "center",
586
- gap: "8px"
587
- },
588
- children: [
589
- /* @__PURE__ */ jsx2(IconComponent, { size: 32, style: { color: textColor, opacity: 0.4 } }),
590
- label && /* @__PURE__ */ jsx2("span", { style: { color: textColor, fontSize: "11px", opacity: 0.4 }, children: label })
591
- ]
592
- }
593
- )
692
+ /* @__PURE__ */ jsx2(Link2, { size: 32, style: { color: textColor, opacity: 0.4 } })
594
693
  ]
595
694
  }
596
- ),
597
- /* @__PURE__ */ jsx2(UrlLabel, { displayUrl })
598
- ] });
599
- if (mediaError && (type === "image" || type === "video")) {
600
- return /* @__PURE__ */ jsx2(PlaceholderCard, { icon: Link2, displayUrl: url });
695
+ ) });
601
696
  }
602
- switch (type) {
603
- case "image":
604
- if (!mediaLoaded) {
605
- return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", alignItems: "center" }, children: [
606
- /* @__PURE__ */ jsxs(
607
- "div",
608
- {
609
- className: cn(defaultClasses.previewSkeleton, classNames.previewSkeleton),
610
- style: {
611
- position: "relative",
612
- backgroundColor: bgColor,
613
- width: "200px",
614
- height: "120px",
615
- overflow: "hidden",
616
- display: "flex",
617
- alignItems: "center",
618
- justifyContent: "center"
619
- },
620
- children: [
621
- /* @__PURE__ */ jsx2("div", { style: { position: "absolute", inset: 0, overflow: "hidden" }, children: /* @__PURE__ */ jsx2(
622
- "div",
623
- {
624
- style: {
625
- position: "absolute",
626
- inset: 0,
627
- background: `linear-gradient(90deg, transparent, ${shimmerColor}, transparent)`,
628
- animation: "sharesheet-shimmer 1.5s infinite"
629
- }
630
- }
631
- ) }),
632
- /* @__PURE__ */ jsx2(Image, { size: 32, style: { color: textColor, opacity: 0.4 } })
633
- ]
634
- }
635
- ),
636
- /* @__PURE__ */ jsx2(UrlLabel, {}),
637
- /* @__PURE__ */ jsx2(
638
- "img",
639
- {
640
- src: url,
641
- alt: alt || "Preview",
642
- onLoad: handleMediaLoad,
643
- onError: handleMediaError,
644
- style: { display: "none" }
645
- }
646
- )
647
- ] });
648
- }
649
- return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", alignItems: "center" }, children: [
650
- /* @__PURE__ */ jsx2(
651
- "img",
697
+ if (!ogData || !hasImage) {
698
+ return /* @__PURE__ */ jsx2("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", width: "100%" }, children: /* @__PURE__ */ jsx2(
699
+ "div",
700
+ {
701
+ className: cn(defaultClasses.previewSkeleton, classNames.previewSkeleton),
702
+ style: {
703
+ position: "relative",
704
+ backgroundColor: bgColor,
705
+ width: "100%",
706
+ maxWidth: "320px",
707
+ aspectRatio: "1.91 / 1",
708
+ overflow: "hidden",
709
+ display: "flex",
710
+ alignItems: "center",
711
+ justifyContent: "center"
712
+ },
713
+ children: /* @__PURE__ */ jsxs(
714
+ "div",
652
715
  {
653
- src: url,
654
- alt: alt || "Preview",
655
- className: cn(defaultClasses.previewImage, classNames.previewImage),
656
716
  style: {
657
- maxWidth: "100%",
658
- maxHeight: "180px",
659
- borderRadius: "12px",
660
- opacity: 1,
661
- transition: "opacity 0.3s ease-in-out"
662
- }
663
- }
664
- ),
665
- /* @__PURE__ */ jsx2(UrlLabel, {})
666
- ] });
667
- case "video":
668
- if (!mediaLoaded) {
669
- return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", alignItems: "center" }, children: [
670
- /* @__PURE__ */ jsxs(
671
- "div",
672
- {
673
- className: cn(defaultClasses.previewSkeleton, classNames.previewSkeleton),
674
- style: {
675
- position: "relative",
676
- backgroundColor: bgColor,
677
- width: "200px",
678
- height: "120px",
679
- overflow: "hidden",
680
- display: "flex",
681
- alignItems: "center",
682
- justifyContent: "center"
683
- },
684
- children: [
685
- /* @__PURE__ */ jsx2("div", { style: { position: "absolute", inset: 0, overflow: "hidden" }, children: /* @__PURE__ */ jsx2(
686
- "div",
687
- {
688
- style: {
689
- position: "absolute",
690
- inset: 0,
691
- background: `linear-gradient(90deg, transparent, ${shimmerColor}, transparent)`,
692
- animation: "sharesheet-shimmer 1.5s infinite"
693
- }
694
- }
695
- ) }),
696
- /* @__PURE__ */ jsx2(Film, { size: 32, style: { color: textColor, opacity: 0.4 } })
697
- ]
698
- }
699
- ),
700
- /* @__PURE__ */ jsx2(UrlLabel, {}),
701
- /* @__PURE__ */ jsx2(
702
- "video",
703
- {
704
- src: url,
705
- poster,
706
- onLoadedData: handleMediaLoad,
707
- onError: handleMediaError,
708
- style: { display: "none" },
709
- muted: true,
710
- playsInline: true,
711
- preload: "metadata"
712
- }
713
- )
714
- ] });
715
- }
716
- return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", alignItems: "center" }, children: [
717
- /* @__PURE__ */ jsxs("div", { style: { position: "relative", borderRadius: "12px", overflow: "hidden" }, children: [
718
- /* @__PURE__ */ jsx2(
719
- "video",
720
- {
721
- src: url,
722
- poster,
723
- className: cn(defaultClasses.previewVideo, classNames.previewVideo),
724
- style: {
725
- maxWidth: "100%",
726
- maxHeight: "180px",
727
- display: "block"
728
- },
729
- muted: true,
730
- playsInline: true,
731
- preload: "metadata"
732
- }
733
- ),
734
- /* @__PURE__ */ jsx2(
735
- "div",
736
- {
737
- style: {
738
- position: "absolute",
739
- inset: 0,
740
- display: "flex",
741
- alignItems: "center",
742
- justifyContent: "center",
743
- pointerEvents: "none"
744
- },
745
- children: /* @__PURE__ */ jsx2(
746
- "div",
717
+ display: "flex",
718
+ flexDirection: "column",
719
+ alignItems: "center",
720
+ justifyContent: "center",
721
+ gap: "8px",
722
+ padding: "16px"
723
+ },
724
+ children: [
725
+ /* @__PURE__ */ jsx2(Link2, { size: 32, style: { color: textColor, opacity: 0.4 } }),
726
+ ogData?.title && /* @__PURE__ */ jsx2(
727
+ "span",
747
728
  {
748
729
  style: {
749
- backgroundColor: "rgba(0, 0, 0, 0.5)",
750
- borderRadius: "50%",
751
- padding: "10px"
730
+ color: textColor,
731
+ fontSize: "12px",
732
+ opacity: 0.6,
733
+ textAlign: "center",
734
+ maxWidth: "280px",
735
+ overflow: "hidden",
736
+ textOverflow: "ellipsis",
737
+ display: "-webkit-box",
738
+ WebkitLineClamp: 2,
739
+ WebkitBoxOrient: "vertical"
752
740
  },
753
- children: /* @__PURE__ */ jsx2(Play, { size: 20, fill: "white", color: "white" })
741
+ children: ogData.title
754
742
  }
755
743
  )
756
- }
757
- )
758
- ] }),
759
- /* @__PURE__ */ jsx2(UrlLabel, {})
760
- ] });
761
- case "audio":
762
- return /* @__PURE__ */ jsx2(PlaceholderCard, { icon: Music, label: filename || "Audio", displayUrl: url });
763
- case "file":
764
- return /* @__PURE__ */ jsx2(PlaceholderCard, { icon: FileText, label: filename || "File", displayUrl: url });
765
- case "link":
766
- default:
767
- return /* @__PURE__ */ jsx2(PlaceholderCard, { icon: Link2, displayUrl: url });
744
+ ]
745
+ }
746
+ )
747
+ }
748
+ ) });
749
+ }
750
+ if (!imageLoaded) {
751
+ return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", width: "100%" }, children: [
752
+ /* @__PURE__ */ jsxs(
753
+ "div",
754
+ {
755
+ className: cn(defaultClasses.previewSkeleton, classNames.previewSkeleton),
756
+ style: {
757
+ position: "relative",
758
+ backgroundColor: bgColor,
759
+ width: "100%",
760
+ maxWidth: "320px",
761
+ aspectRatio: "1.91 / 1",
762
+ overflow: "hidden",
763
+ display: "flex",
764
+ alignItems: "center",
765
+ justifyContent: "center"
766
+ },
767
+ children: [
768
+ /* @__PURE__ */ jsx2("div", { style: { position: "absolute", inset: 0, overflow: "hidden" }, children: /* @__PURE__ */ jsx2(
769
+ "div",
770
+ {
771
+ style: {
772
+ position: "absolute",
773
+ inset: 0,
774
+ background: `linear-gradient(90deg, transparent, ${shimmerColor}, transparent)`,
775
+ animation: "sharesheet-shimmer 1.5s infinite"
776
+ }
777
+ }
778
+ ) }),
779
+ /* @__PURE__ */ jsx2(Image, { size: 32, style: { color: textColor, opacity: 0.4 } })
780
+ ]
781
+ }
782
+ ),
783
+ /* @__PURE__ */ jsx2(
784
+ "img",
785
+ {
786
+ src: ogImage,
787
+ alt: ogData.title || "Preview",
788
+ onLoad: handleImageLoad,
789
+ onError: handleImageError,
790
+ style: { display: "none" }
791
+ }
792
+ )
793
+ ] });
768
794
  }
795
+ return /* @__PURE__ */ jsx2("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", width: "100%" }, children: /* @__PURE__ */ jsx2(
796
+ "img",
797
+ {
798
+ src: ogImage,
799
+ alt: ogData.title || "Preview",
800
+ className: cn(defaultClasses.previewImage, classNames.previewImage),
801
+ style: {
802
+ width: "100%",
803
+ maxWidth: "320px",
804
+ height: "auto",
805
+ borderRadius: "12px",
806
+ opacity: 1,
807
+ transition: "opacity 0.3s ease-in-out"
808
+ }
809
+ }
810
+ ) });
769
811
  };
770
812
  return /* @__PURE__ */ jsxs("div", { className: cn(defaultClasses.root, classNames.root, className), children: [
771
813
  /* @__PURE__ */ jsx2("style", { dangerouslySetInnerHTML: { __html: shimmerKeyframes } }),
@@ -787,7 +829,7 @@ function ShareSheetContent({
787
829
  }
788
830
  )
789
831
  ] }),
790
- showPreview && /* @__PURE__ */ jsx2("div", { className: cn(defaultClasses.preview, classNames.preview), children: renderPreview() }),
832
+ /* @__PURE__ */ jsx2("div", { className: cn(defaultClasses.preview, classNames.preview), children: renderPreview() }),
791
833
  /* @__PURE__ */ jsx2("div", { className: cn(defaultClasses.grid, classNames.grid), children: visibleButtons.map((btn) => /* @__PURE__ */ jsxs(
792
834
  "button",
793
835
  {
@@ -830,8 +872,8 @@ import { Drawer } from "vaul";
830
872
  import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
831
873
  var defaultDrawerClasses = {
832
874
  overlay: "fixed inset-0 z-[70]",
833
- drawer: "flex flex-col rounded-t-[14px] h-[70%] mt-24 fixed bottom-0 left-0 right-0 z-[80] border-t outline-none",
834
- drawerInner: "p-4 rounded-t-[14px] flex-1 overflow-auto",
875
+ drawer: "flex flex-col rounded-t-[14px] max-h-[90%] fixed bottom-0 left-0 right-0 z-[80] border-t outline-none",
876
+ drawerInner: "p-4 pb-8 rounded-t-[14px] overflow-auto",
835
877
  handle: "mx-auto w-12 h-1.5 shrink-0 rounded-full mb-6",
836
878
  trigger: ""
837
879
  };
@@ -842,7 +884,6 @@ function ShareSheetDrawer({
842
884
  title = "Share",
843
885
  shareUrl,
844
886
  shareText,
845
- preview,
846
887
  downloadUrl,
847
888
  downloadFilename,
848
889
  disabled,
@@ -920,7 +961,6 @@ function ShareSheetDrawer({
920
961
  title,
921
962
  shareUrl,
922
963
  shareText,
923
- preview,
924
964
  downloadUrl,
925
965
  downloadFilename,
926
966
  className,
@@ -954,6 +994,8 @@ export {
954
994
  CSS_VARS_UI,
955
995
  CSS_VAR_DEFAULTS,
956
996
  CSS_VAR_UI_DEFAULTS,
997
+ MOBILE_ONLY_PLATFORMS,
998
+ MOBILE_PREFERRED_PLATFORMS,
957
999
  PLATFORMS,
958
1000
  PLATFORM_COLORS,
959
1001
  PLATFORM_CSS_VARS,
@@ -964,14 +1006,21 @@ export {
964
1006
  ShareMenuDrawer,
965
1007
  ShareSheetContent,
966
1008
  ShareSheetDrawer,
1009
+ checkPlatformAvailability,
1010
+ clearOGCache,
967
1011
  cn,
1012
+ fetchOGData,
968
1013
  generateCssVarDefaults,
1014
+ getAllPlatformAvailability,
969
1015
  getAllPlatforms,
970
1016
  getPlatform,
971
1017
  getPlatformColor,
972
1018
  getPlatformIcon,
973
1019
  getPlatformLabel,
974
1020
  getSafeUrl,
1021
+ isAndroidDevice,
1022
+ isIOSDevice,
1023
+ isMobileDevice,
975
1024
  openInstagram,
976
1025
  openThreads,
977
1026
  openTikTok,
@@ -985,7 +1034,9 @@ export {
985
1034
  shareToX,
986
1035
  shareViaEmail,
987
1036
  shareViaSMS,
1037
+ useOGData,
988
1038
  useShareMenu,
989
- useShareSheet
1039
+ useShareSheet,
1040
+ warnUnavailablePlatform
990
1041
  };
991
1042
  //# sourceMappingURL=index.mjs.map